简体   繁体   中英

perl batch rename files in command line

I want to rename files with 'sr' in their names, replacing 'sr' with 'SR'. This one succeeded:

ls | perl -e 'while(<>){chomp;if(/(.*)sr(.*)/){rename $_,$1."SR".$2}}'

But this one failed:

ls | perl -e "while(<>){chomp;if(/sr/){rename $_,$\`.'SR'.($')}}"

with this error message:

Not enough arguments for rename at -e line 1, near "rename ,"`
Execution of -e aborted due to compilation errors.

It seems that $_ has become an empty string, but I don't quite understand why. Thanks for any explanations.

Now quotes have been an interesting problem and this is my test:

ls | perl -e "while(<>){chomp;if(/sr/){print $_;print\"\n\";print $\`,$&,($');print \"\n\";print $_,$\`,$&,($');print\"\n\";print $_;print\"\n\"}}"

outputs this:

3sr
3sr
3sr
3sr
sr1
sr1
sr1
sr1
sr2
sr2
sr2
sr2

it seems that when using alone, $_ is not empty; but it become empty when using along with $`,$& and $'. According to the last line of each file, I guess $_ has temporarily changed when not using alone?

Besides, according to a1111exe's answer, I test this:

ls | perl -e "while(<>){chomp;if(/sr/){print \$_,$\`,$&,($');print \"\n\"}}"

and got this:

3sr3sr
sr1sr1
sr2sr2

First in linux we should use single quote instead of double quote.

And instead of ls command you can use perl inbuilt function glob

And to capture the pre and post match you can use the $POSTMATCH and $PREMATCH from English module

so your one liner should be

perl -MEnglish -e 'while(<*>){chomp;if(/sr/){rename $_,$PREMATCH."SR".$POSTMATCH}}'

EDITED

Single quote and double quote is not about Perl this is about shell.

Single quote

Enclosing characters in single quotes (') preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.

Double quote

Enclosing characters in double quotes ('"') preserves the literal value of all characters within the quotes, with the exception of '$', '`', '\\', and, when history expansion is enabled, '!'.

In shell script we are accessing the shell variable prefix with $ , so while using $ inside the double quote it is looking for the shell variable not a Perl variable. For example you can run the following line in your terminal,

m=4; perl -e "print $m;"

Here

m=4; perl -e "print $m;"
^                   ^ 
|                   Accessing shell variable
Assigning shell variable

Output is 4 . Because m is shell variable you are accessing the shell variable inside your Perl script.

And in windows, we need to use double-quote instead of single quote

It seems that double quotes mess between your shell environment and Perl. You can certainly do what @mkHun suggested. One other way:

ls | perl -e 'while(<>){chomp;($new=$_)=~s/sr/SR/g;rename $_,$new}'

Also, if you escape the '$' sigil in '$_', your oneliner will work too:

ls | perl -e "while(<>){chomp;if(/sr/){rename \$_,$\`.'SR'.$'}}"

I still don't get why though.. But it really seems like bash/perl interpolation issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM