0

I currently have a script where I rename files by removing whitespace and certain names. This is about 200 names so far so I though an array of names I want to exclude would be a better option.

prename -v 's/ /_/g' *

prename -v 's/_-_/_/g' *

prename -v 's/_\(Summer-HD\)//ig' *

prename -v 's/_\(Hammer\)//ig' *

prename -v 's/_\(Hardware-Hybrid\)//g' *

prename -v 's/_\(digital\)//ig' *

prename -v 's/_\(Resolution-SD\)//ig' *

This is what i have tried so far, a for loop to iterate over the names I want to exclude and but that has not worked.

exclude=('(Summer-HD)' '(Hammer)' '(digital)' '(Resolution-SD)' '(Vacation)' '(Hammer-Hybrid)')

for x in "${exclude[@]}";
    do prename -v 's/$x/_/g' * {} \;
done

This for loop does not work at all and just leaves me with a blinking cursor. I'm not sure if I can pass a variable to prename. I modified the for loop a bit on some advise about wrapping things in double quotes.

for x in "${exclude[@]}";
    do prename -v 's/$x/_/g' *"$x"* {} \;
done

This also does not work, and now I have no idea what all is going on here. I still want to have the array for the names since I currently have more than 200 that i would like to remove. As for prename, I'm not married to the idea, I have heard sed could help or awk. Neither I am comfortable with to do this in. Thanks for any ideas or help provided.

1
  • BTW, it seems you're confusing bash for loops with find syntax. {} \; is used with find's -exec and -execdir to pass filename args to the program being executed.
    – cas
    Commented Nov 14, 2022 at 1:18

2 Answers 2

0

You can define the array (or a scalar variable containing a regex made up from a list) inside the prename script - remember that you can use any valid perl code inside a prename script (because a prename script is a specialised perl script). e.g.

$ touch foo_\(Summer-HD\)_\(digital\).mkv
$ prename -n 'BEGIN {
                our $exclude=join("|", qw(Summer-HD Hammer digital Resolution-SD Vacation Hammer-Hybrid));
              };

              our $exclude;
              s/_\((?:$exclude)\)//ig;' *
rename(foo_(Summer-HD)_(digital).mkv, foo.mkv)

There's a few things worth noting here:

  1. Variable scope is very important in a rename script, and the use strict pragma is in effect. See perldoc strict (there's a lot more to it but, tl;dr: with strict you can't use variables you haven't previously declared in the current scope).
  2. The $exclude variable is defined in a BEGIN {} block so that it is only executed ONCE when the script is executed, not once for every filename. It contains the array joined by | characters - i.e. regex alternations.
  3. It's defined as an our variable so that is shared outside of the BEGIN block, i.e. it's available within the entire scope of the File::Rename package. That's probably more than you care to know, so just think of it as a global variable for the rename script. The main code block also needs to declare it (with just our $exclude;). See perldoc -f our
  4. qw() is one of perl's quoting operators, which turns a list of whitespace-separated bare words into an array. See perldoc -f qw. BTW, in perl, "array" and "list" are almost synonyms - see perldoc -q difference.*list.*array

Also worth noting is that instead of running rename multiple times, you should run it once with a longer script (or with multiple -e '...script...' options). e.g.

$ prename -n 'BEGIN {
                our $exclude=join("|", qw(Summer-HD Hammer digital Resolution-SD Vacation Hammer-Hybrid));
              };

              our $exclude;

              s/ /_/g;
              s/_-_/_/g;
              s/_\((?:$exclude)\)//ig;' *
0

It's easier with zsh:

exclude=(
  '(Summer-HD)'
  '(Hammer)'
  '(digital)'
  '(Resolution-SD)'
  '(Vacation)'
  '(Hammer-Hybrid)'
)

pattern="_(${(j[|])${(b@)exclude}})"

autoload -Uz zmv
zmv '*' '${f//$~pattern}'

Where ${(b)exclude} escapes the glob operators in the elements of $exclude, ${(j[|])...} joins the result with |, so we end up with $pattern being _(exclude1|exclude2...) (specifically: _(\(Summer-HD\)|\(Hammer\)|\(digital\)|\(Resolution-SD\)|\(Vacation\)|\(Hammer-Hybrid\))), and matches of that are replaced with nothing using the ${f//pattern[/replacement]} operator from ksh93 inside the zmv batch renamer.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.