Home > front end >  batch rename matching files using 1st field to replace and 2nd as search criteria
batch rename matching files using 1st field to replace and 2nd as search criteria

Time:05-14

I have a very large selection of files eg.

foo_de.vtt, foo_en.vtt, foo_es.vtt, foo_fr.vtt, foo_pt.vtt, baa_de.vtt, baa_en.vtt, baa_es.vtt, baa_fr.vtt, baa_pt.vtt... etc.

I have created a tab separated file, filenames.txt containing the current string and replacement string eg.

foo    1000
baa    1016
...etc

I want to rename all of the files to get the following:

1000_de.vtt, 1000_en.vtt, 1000_es.vtt, 1000_fr.vtt, 1000_pt.vtt, 1016_de.vtt, 1016_en.vtt, 1016_es.vtt, 1016_fr.vtt, 1016_pt.vtt

I know I can use a utility like rename to do it manually term by term eg: rename 's/foo/1000/g' *.vtt

could i chain this into an awk command so that it could run through the filenames.txt? or is there an easier way to do it just in awk? I know I can rename with awk such as:

find . -type f | awk -v mvCmd='mv "%s" "%s"\n' \
    '{ old=$0;
       gsub(/foo/,"1000");
       printf mvCmd,old,$0;
     }' | sh

How can I get awk to process filenames.txt and do all of this in one go? This question is similar but uses sed. I feel that being tab separated this should be quite easy in awk?

First ever post so please be gentle!

Solution

Thanks for all your help. Ultimately I was able to solve by adapting your answers to the following:

while read new old; do
  rename "s/$old/$new/g" *.vtt;
done < filenames.txt

CodePudding user response:

I'm assuming that the strings in the TSV file are literals (not regexes nor globs) and that the part to be replaced can be located anywhere in the filenames.

With that said, you can use mv with shell globs and bash parameter expansion:

#!/bin/bash

while IFS=$'\t' read -r old new
do
    for f in *"$old"*.vtt
    do
        mv "$f" "${f/"$old"/$new}"
    done
done < file.tsv

Or with GNU rename (more performant):

while IFS=$'\t' read -r old new
do
    rename "$old" "$new" *"$old"*.vtt
done < file.tsv

CodePudding user response:

Using sed

while read old new; do 
    sed "s/$old\(.*\)/mv & $new\1/e" <(find . -name '*.vtt' -printf '%f\n')  
done < filenames.txt

CodePudding user response:

This might work for you (GNU sed and rename):

sed -E 's#(.*)\t(.*)#rename -n '\''s/\1/\2/'\'' \1*#e' ../file

This builds a script which renames the files in the current directory using file to match and replace parts of the filenames.

Once you are happy with the results, remove the -n and the renaming will be enacted.

  • Related