Home > Enterprise >  How to pass captured regex group to a shell command inside perl-rename
How to pass captured regex group to a shell command inside perl-rename

Time:08-04

I have a set of files that I want to batch rename using rename utility available in WSL Ubuntu. My files names contains the following pattern and I want to correct the date format in the files.

file_10Feb2022.pptx
file_10Mar2022.pptx
file_17Feb2022.pptx
file_17Mar2022.pptx
file_24Feb2022.pptx
file_3Feb2022.pptx
file_3Mar2022.pptx

I tried to use the following command to rename

rename -n "s/_(.*)\./_`date %F -d \1`\./g" *.pptx

I capture the date part with regex and I am trying to use date command (inside the ``) to format correctly, but I am unable to pass the captured regex group (\1) to the shell command.

Running it with rename -n flags returns the following output, where it would try to rename to current date (2022-08-03) instead of the date specified.

rename(file_10Feb2022.pptx, file_2022-08-03.pptx)
rename(file_10Mar2022.pptx, file_2022-08-03.pptx)
rename(file_17Feb2022.pptx, file_2022-08-03.pptx)
rename(file_17Mar2022.pptx, file_2022-08-03.pptx)
rename(file_24Feb2022.pptx, file_2022-08-03.pptx)
rename(file_3Feb2022.pptx, file_2022-08-03.pptx)
rename(file_3Mar2022.pptx, file_2022-08-03.pptx)

I have another folder full of files which have suffix with varying date formats and I would like to capture it and let date command deal with the format, instead of me capturing individual parts like date, month and year. Any ideas on how to execute this properly?

CodePudding user response:

This is probably getting beyond where a one-liner is a good idea but:

$ rename 's{_(.*?)(\.[^.] )$}{
    my ($d,$s) = ($1,$2);
    my $nd = `date  %F -d "$d"`;
    chomp $nd;
    $? ? $& : "_$nd$s" 
}e' file_*
  • s{}{}e - search and replace, treating replacement as code
  • code in backticks is the shell command (with interpolation)
  • if $? is set something went wrong, return original value; else do replacement
  • date errors will appear on stderr as usual; affected files will not be renamed
  • chomp removes the newline received from the backticks, otherwise it would end up in the filename
  • ?: is the trinary operator: if ? then : else
  • some input could be unsafe when passed to the shell and should be escaped; @ikegami notes that the shell can be avoided entirely. For example, something like:
use IPC::System::Simple qw( capturex );
my $nd = capturex( "date", " %F", "-d", $d );

The reason your command returns current date:

rename -n "s/_(.*)\./_`date  %F -d \1`\./g" *.pptx

is that because you used double-quotes, the backticks are expanded by the shell, not by rename (but you need /e for rename not to take the backtick statement as literal text to insert.

  • Related