in reply to Rename all files on remote server to *.bak recursively

I would change the approach from your script (sending a shell command loop to the remote side) to a three-step approach:

  1. Get the list of all remote files
  2. Munge the list in Perl
  3. Send a list of mv -i commands to the remote side

Using the three steps makes it much, much easier to review the list of commands before they are executed.

The relevant parts of the script would be:

# Get list of remote files my @remote_files= qx(ssh $uid $h 'find $dirname');
# Munge filenames to commands: my @commands= map { sprintf "mv -i '%s' '%s.bak'", quotemeta($_), quotemeta($_) } @remote_files;
# Send list of commands to the remote side: # First, a dry-run instead of actually doing that: my $remote= \*STDOUT; # Use this to actually do the remote execution: #open $remote, "| ssh -q -l $uid $h"; print { $remote } join "\n", @commands;

Replies are listed 'Best First'.
Re^2: Rename all files on remote server to *.bak recursively
by PerlSufi (Friar) on Jun 05, 2014 at 14:01 UTC
    Corion ++ !! I did not know about the quotemeta function.
    That is quite a neat function indeed..thanks
Re^2: Rename all files on remote server to *.bak recursively
by nancylt723 (Initiate) on Jun 06, 2014 at 12:31 UTC

    Thanks for the suggestion; however my files were not renamed: My code is now:

    #!/usr/bin/perl my $h="testapp01"; my $dirname="/home/wasbatsrv/tmp/testbak"; my $uid="wasbatsrv"; my @remote_files= qx(ssh $uid\@$h 'find $dirname'); # Munge filenames to commands: my @commands= map { sprintf "mv -i '%s' '%s.bak'", quotemeta($_), quo +temeta($_) } @remote_files; # Send list of commands to the remote side: # First, a dry-run instead of actually doing that: my $remote= \*STDOUT; # Use this to actually do the remote execution: open $remote, "| ssh -q $uid\@$h"; print { $remote } join "\n", @commands;

    But the files are not renamed and this is the output:

    Pseudo-terminal will not be allocated because stdin is not a terminal +. mv: cannot stat `\\/home\\/wasbatsrv\\/tmp\\/testbak\\\n': No such fil +e or directory mv: cannot stat `\\/home\\/wasbatsrv\\/tmp\\/testbak\\/testbakr\\\n': +No such file or directory mv: cannot stat `\\/home\\/wasbatsrv\\/tmp\\/testbak\\/testbakr\\/thre +e\\.properties\\\n': No such file or directory mv: cannot stat `\\/home\\/wasbatsrv\\/tmp\\/testbak\\/testbakr\\/four +\\.properties\\\n': No such file or directory mv: cannot stat `\\/home\\/wasbatsrv\\/tmp\\/testbak\\/two\\.propertie +s\\\n': No such file or directory mv: cannot stat `\\/home\\/wasbatsrv\\/tmp\\/testbak\\/one\\.propertie +s\\\n': No such file or directory

    Here is the directory listing:

    [wasbatsrv@testapp01 testbak]$ ls one.properties testbakr two.properties

      Does the command work when you first print it out and then run it manually in the shell?

      I guess the problem results from me using both, single quotes and quotemeta when constructing the command line.

      Maybe you can make sure that no filename contains a backslash or a single quote. Then you can eliminate both calls to quotemeta and replace them by $_ directly.

      Note that your problem has nothing to do with Perl anymore and is only a matter of constructing the correct shell statement now.

        I tried removing the quotmeta, but as far as I can tell, this would also try to rename the directories, also, which I do not want to do. I only want to rename the files.