3

I am trying to rename all files in a remote directory over SSH or SFTP. The rename should convert the file into a date extension, for example .txt into .txt.2016-05-25.

I have the following command to loop each .txt file and try to rename, but am getting an error:

ssh $user@$server "for FILENAME in $srcFolder/*.txt; do mv $FILENAME $FILENAME.$DATE; done"

The error I am getting is:

mv: missing destination file operand after `.20160525_1336'

I have also tried this over SFTP with no such luck. Any help would be appreciated!

Derek
  • 33
  • 1
  • 3
  • `$srcFolder`, `$FILENAME` and `$DATE` are (probably) being expanded by your local shell. Have you tried using single quotes for the whole command? (And while you're at it quote the variables within the command, in case filenames contain ‘special’ characters.) – Biffen May 25 '16 at 17:52

3 Answers3

2

You need to escape (or single-quote) the $ of variables in the remote shell. It's also recommended to quote variables that represent file paths:

ssh $user@$server "for FILENAME in '$srcFolder'/*.txt; do mv \"\$FILENAME\" \"\$FILENAME.$DATE\"; done"
janos
  • 120,954
  • 29
  • 226
  • 236
  • 2
    If `$srcFolder` contains spaces the second one will fail. Even the first will give unexpected results. Preferred: `ssh "$user@$server" 'for FILENAME in '"'$srcFolder/'"'*.txt; do ...'` – Andreas Louv May 25 '16 at 18:14
  • 1
    To be safe, the two arguments to `mv` should also be quoted on the remote side: `mv \"\$FILENAME\" \"\$FILENAME.$DATE\"` – chepner May 25 '16 at 18:17
  • Thank you, both of these worked out perfectly. Since my srcFolder does not have spaces I used it with the escape characters, but thanks to both of you. – Derek May 31 '16 at 20:29
1

Try this:

By using rename ( tool):

ssh user@host /bin/sh <<<$'
    rename \047use POSIX;s/$/strftime(".%F",localtime())/e\047 "'"$srcFolder\"/*.txt" 

To prepare/validate your command line, replace ssh...bin/sh by cat:

cat <<<$'
    rename \047use POSIX;s/$/strftime(".%F",localtime())/e\047 "'"$srcFolder\"/*.txt" 

will render something like:

rename 'use POSIX;s/$/strftime(".%F",localtime())/e' "/tmp/test dir"/*.txt

And you could localy try (ensuring $srcFolder contain a path to a local test folder):

/bin/sh <<<$'
    rename \047use POSIX;s/$/strftime(".%F",localtime())/e\047 "'"$srcFolder\"/*.txt" 

Copy of your own syntax:

ssh $user@$server /bin/sh <<<'for FILENAME in "'"$srcFolder"'"/*.txt; do
     mv "$FILENAME" "$FILENAME.'$DATE'";
  done'

Again, you could locally test your inline script:

sh <<<'for FILENAME in "'"$srcFolder"'"/*.txt; do
    mv "$FILENAME" "$FILENAME.'$DATE'";
done'

or preview by replacing sh by cat.

F. Hauri - Give Up GitHub
  • 64,122
  • 17
  • 116
  • 137
0

When using/sending variables over SSH, you need to be careful what is a local variable and which is a remote variable. Remote variables must be escaped; otherwise they will be interpreted locally versus remotely as you intended. Other characters also need to be escaped such as backticks. The example below should point you in the right direction:

Incorrect

user@host1:/home:> ssh user@host2 "var=`hostname`; echo \$var"

host1

Correct

user@host1:/home:> ssh user@host2 "var=\`hostname\`; echo \$var"

host2

Inetquestion
  • 165
  • 1
  • 15