PDA

View Full Version : Terminal command via ssh




Ace134blue
Oct 12, 2010, 11:21 PM
So trying to delete unnecessary language packs, heres the script but it wont work

for file in `find . -type d -name "*.lproj" -not -iname "en*.lproj" -not -iname "ge*.lproj" -not -iname "de*.lproj" -exec echo {} ; | sed -e 's/.///'`; do rm -vr ./ ; done

heres the error

-sh: command substitution: line 1: syntax error near unexpected token `|'
-sh: command substitution: line 1: `find . -type d -name "*.lproj" -not -iname "en*.lproj" -not -iname "ge*.lproj" -not -iname "de*.lproj" -exec echo {} ; | sed -e 's/.///''

Can anyone fix it? Tried it on Putty in windows and tried cyber duck/ terminal in OSX



jahala
Oct 13, 2010, 12:14 AM
for file in `find . -type d -name "*.lproj" -not -iname "en*.lproj" -not -iname "ge*.lproj" -not -iname "de*.lproj" -exec echo {} \; | sed -e 's#./##'`; do echo "$file"; done

I did not want to actually delete those directories, so I changed the rm command to an echo statement instead.

You were missing a backslash before the first semicolon. You need that backslash to pass the actual semicolon instead of marking the start of the next command. It looks like you were trying to match the "./" at the beginning of each directory in your sed statement. To do that you have to use a different character to mark the beginning and end of the regular expression, hence the # symbols.

That regex in sed actually matches any character followed by a slash. If you are trying to match the period, you should use this sed statement:

sed -e 's#\./##'

That will match a period followed by a forward slash.

What does your thread title mean (terminal command via ssh)? You have a shell via ssh and are running this command or you want to pass this command on the command line when you run ssh, e.g. "ssh user@host mycommand" ?

Ace134blue
Oct 13, 2010, 03:41 PM
for file in `find . -type d -name "*.lproj" -not -iname "en*.lproj" -not -iname "ge*.lproj" -not -iname "de*.lproj" -exec echo {} \; | sed -e 's#./##'`; do echo "$file"; done

I did not want to actually delete those directories, so I changed the rm command to an echo statement instead.

You were missing a backslash before the first semicolon. You need that backslash to pass the actual semicolon instead of marking the start of the next command. It looks like you were trying to match the "./" at the beginning of each directory in your sed statement. To do that you have to use a different character to mark the beginning and end of the regular expression, hence the # symbols.

That regex in sed actually matches any character followed by a slash. If you are trying to match the period, you should use this sed statement:

sed -e 's#\./##'

That will match a period followed by a forward slash.

What does your thread title mean (terminal command via ssh)? You have a shell via ssh and are running this command or you want to pass this command on the command line when you run ssh, e.g. "ssh user@host mycommand" ?

Sorry for not being specific. I am trying to clean up Langauge packs from an iphone/ipod by using that command in terminal thru ssh root@host. I do want to delete the .proj folders, so would i just put rm back in? I am using cryberduck to browse the files, and since it doesnt have built in terminal i use OSXs terminal.

Ace134blue
Oct 13, 2010, 07:24 PM
for file in `find . -type d -name "*.lproj" -not -iname "en*.lproj" -not -iname "ge*.lproj" -not -iname "de*.lproj" -exec echo {} \; | sed -e 's#./##'`; do echo "$file"; done

I did not want to actually delete those directories, so I changed the rm command to an echo statement instead.

You were missing a backslash before the first semicolon. You need that backslash to pass the actual semicolon instead of marking the start of the next command. It looks like you were trying to match the "./" at the beginning of each directory in your sed statement. To do that you have to use a different character to mark the beginning and end of the regular expression, hence the # symbols.

That regex in sed actually matches any character followed by a slash. If you are trying to match the period, you should use this sed statement:

sed -e 's#\./##'

That will match a period followed by a forward slash.

What does your thread title mean (terminal command via ssh)? You have a shell via ssh and are running this command or you want to pass this command on the command line when you run ssh, e.g. "ssh user@host mycommand" ?

find . -type d -name "*.lproj" -not -iname "en*.lproj" -exec echo {} \; | sed -e 's#./##'`; do rm -vr ./ ; done

I tried that and it says sh: syntax error near unexpected token 'do'

angelwatt
Oct 14, 2010, 08:19 AM
find . -type d -name "*.lproj" -not -iname "en*.lproj" -exec echo {} \; | sed -e 's#./##'`; do rm -vr ./ ; done

I tried that and it says sh: syntax error near unexpected token 'do'

Looks like there's a stray back tick right before the semicolon before the do. I highlighted it in bold red in the quoted text above.

jahala
Oct 14, 2010, 09:09 AM
Looks like there's a stray back tick right before the semicolon before the do. I highlighted it in bold red in the quoted text above.

The stray backtick is not the problem. The problem is that he forgot the beginning of the for loop that has the matching opening back tick. Specifically, he forgot "for file in `".

But looking at that rm command, I noticed that it does not do what the OP intended. That command will just result in an error saying "./ is a directory". The full, correct command is posted below:

for file in `find . -type d -name "*.lproj" -not -iname "en*.lproj" -not -iname "ge*.lproj" -not -iname "de*.lproj" -exec echo {} \; | sed -e 's#./##'`; do rm -vr "$file"; done

Ace134blue
Oct 14, 2010, 09:30 PM
The stray backtick is not the problem. The problem is that he forgot the beginning of the for loop that has the matching opening back tick. Specifically, he forgot "for file in `".

But looking at that rm command, I noticed that it does not do what the OP intended. That command will just result in an error saying "./ is a directory". The full, correct command is posted below:

for file in `find . -type d -name "*.lproj" -not -iname "en*.lproj" -not -iname "ge*.lproj" -not -iname "de*.lproj" -exec echo {} \; | sed -e 's#./##'`; do rm -vr "$file"; done

Thanks, but it says syntax error unexpected token "do

ulbador
Oct 14, 2010, 10:34 PM
I broke it out into a shell script and it worked



#!/bin/bash

for file in `find . -type d -name "*.lproj" -not -iname "en*.lproj" -not -iname "ge*.lproj" -not -iname "de*.lproj" -exec echo {} \; | sed -e 's#./##'`;
do
echo $file;
done



Just drop that in like temp.sh and then run
sh temp.sh

Of course your have to change the echo $file to rm -vrf (force) though that command scares the hell of me doing it like this...

That returned a TON of crap too. You'll definitely want to check the output with the echo before you drop the "rm" back in. It looks like it's having a problem with the spaces and splitting them out onto separate lines. The sed will probably have to be fixed

jahala
Oct 15, 2010, 11:29 AM
Which directory are you running this script from? My example assumes you are in <Application Name>/Contents/Resources directory.

Ace134blue
Oct 15, 2010, 10:45 PM
Which directory are you running this script from? My example assumes you are in <Application Name>/Contents/Resources directory.

The / directory, since there is literally a proj files in each folder

chown33
Oct 16, 2010, 02:57 PM
Why does this need a 'for' loop at all? Why not use just the capabilities of the 'find' command?

First, there is a -ok predicate that is identical to the -exec predicate, except it prompts for confirmation first.

Second, there seems to be no reason for using the output of find as a list of 'for' words, when find by itself is capable of traversing directories and deleting things.

Third, if the traversal originates from /, then simply use / instead of . and the {} parameter will get the full pathname of the item. If you want a specific device pathname, then use a specific device pathname instead of . or /.

Untested example, with \-newlines for readability:
find / -type d \
-name "*.lproj" -not -iname "en*.lproj" \
-not -iname "ge*.lproj" -not -iname "de*.lproj" \
-ok /bin/rm -vrf '{}' \;

Since find's default is pre-order traversal of directories, any directory seen that matches all the criteria before -ok will be deleted (or not) before any of its contents are.

It might also be wise to use the 'find' options that prevent following symlinks or moving to another block device.

Ace134blue
Oct 17, 2010, 12:44 AM
Why does this need a 'for' loop at all? Why not use just the capabilities of the 'find' command?

First, there is a -ok predicate that is identical to the -exec predicate, except it prompts for confirmation first.

Second, there seems to be no reason for using the output of find as a list of 'for' words, when find by itself is capable of traversing directories and deleting things.

Third, if the traversal originates from /, then simply use / instead of . and the {} parameter will get the full pathname of the item. If you want a specific device pathname, then use a specific device pathname instead of . or /.

Untested example, with \-newlines for readability:
find / -type d \
-name "*.lproj" -not -iname "en*.lproj" \
-not -iname "ge*.lproj" -not -iname "de*.lproj" \
-ok /bin/rm -vrf '{}' \;

Since find's default is pre-order traversal of directories, any directory seen that matches all the criteria before -ok will be deleted (or not) before any of its contents are.

It might also be wise to use the 'find' options that prevent following symlinks or moving to another block device.

Thanks, no errors now. But it does nothing.
I entered those cmds and hit enter then it does find every .lproj file and it comes With system/library/Xxx/XXX/xx.lproj > ?
It just says a question mark for each one, which i have to press enter a thousand times. So what do i do?

chown33
Oct 17, 2010, 02:08 AM
Thanks, no errors now. But it does nothing.
I entered those cmds and hit enter then it does find every .lproj file and it comes With system/library/Xxx/XXX/xx.lproj > ?
It just says a question mark for each one, which i have to press enter a thousand times. So what do i do?

Read the man page for the 'find' command.

First, it should prompt with the command name, /bin/rm, followed by the options and pathname, -vrf /system/whatever.

If you don't see /bin/rm, then it's not working.

If you don't see a pathname that starts with /, it's not working.

If you don't understand what you're seeing, then post a real example of what you see. Copy and paste it into a post, don't just type something that somewhat looks like what you see. We need to see EXACTLY what it's asking.

Second, if you read the man page for 'find' and look at the -ok predicate, it tells you that you have to enter 'y' (or anything that start with 'y', such as 'yes'). If you only enter newline, then the rm command is not run, and the directory is not deleted.

Third, if you want to delete things WITHOUT CONFIRMATION, substitute -exec for -ok, and it will delete without confirmation.

All the above can be learned simply by reading the man page for the 'find' command. Which leads me to a question: if you haven't read the man page for 'find', how did you come up with the script you originally posted? Do you have any significant experience in using the command line, or is this just something you found and tried?

Fourth, if you're not running as root, then you won't be able to delete things at all.

Fifth, if you don't have a backup, you should probably make one before attempting anything else. You should do this first, even though I've listed it last.

Ace134blue
Oct 18, 2010, 12:35 AM
Read the man page for the 'find' command.

First, it should prompt with the command name, /bin/rm, followed by the options and pathname, -vrf /system/whatever.

If you don't see /bin/rm, then it's not working.

If you don't see a pathname that starts with /, it's not working.

If you don't understand what you're seeing, then post a real example of what you see. Copy and paste it into a post, don't just type something that somewhat looks like what you see. We need to see EXACTLY what it's asking.

Second, if you read the man page for 'find' and look at the -ok predicate, it tells you that you have to enter 'y' (or anything that start with 'y', such as 'yes'). If you only enter newline, then the rm command is not run, and the directory is not deleted.

Third, if you want to delete things WITHOUT CONFIRMATION, substitute -exec for -ok, and it will delete without confirmation.

All the above can be learned simply by reading the man page for the 'find' command. Which leads me to a question: if you haven't read the man page for 'find', how did you come up with the script you originally posted? Do you have any significant experience in using the command line, or is this just something you found and tried?

Fourth, if you're not running as root, then you won't be able to delete things at all.

Fifth, if you don't have a backup, you should probably make one before attempting anything else. You should do this first, even though I've listed it last.

Thanks man, i really appreciate it.
Sorry anyways, much more used to linux command lines. :P

chown33
Oct 18, 2010, 12:56 AM
Sorry anyways, much more used to linux command lines. :P

The GNU/Linux find command has -exec and -ok, the same as Mac OS X's find. In fact, I don't see any predicate used in this case that isn't in the Linux find.

Ace134blue
Oct 18, 2010, 01:01 AM
The GNU/Linux find command has -exec and -ok, the same as Mac OS X's find. In fact, I don't see any predicate used in this case that isn't in the Linux find.

Im just saying, i rarely use OSXs terminal and since the previous command didnt work i figured they were different