0

I have several files in a folder. I also have a csv file, containing the files name (without extension) listed in a specific order. I would like to rename the files in the folder to include the position in the list of the text file at the beginning of the file name.

In other words, my folder contains:

aaa.txt, bbb.txt, ccc.txt

The filename.csv contains:

ccc
aaa
bbb

What I want to obtain is:

1_ccc.txt, 2_aaa.txt 3_bbb.txt 

Can I do this in bash?

1
for i in *.txt
do line=$(grep -nx -m 1 -- "${i%%.*}" filename.csv | cut -f 1 -d ':')
name=${line}_${i}
mv -- "$i" "$name" 
done

explanation

"${i%%.*}": As suggested by Kusalananda, takes the value of $i, strip off the pattern .* from the tail of the value (more info parameter expansion)

grep -nF --

  • -x matches whole line
  • -m 1 stop reading file after 1 matching line (to avoid grep to read all lines if the file is long)
  • -- is being used to signify the end of the options (more -- in shell)

  • -n returns line number instead of the line itself in following format

    2:aaa 3:bbb 1:ccc

cut -f 1 -d ':' extracts field 1 with : delimeter from the above result

4
  • $(echo "$i" | cut -f 1 -d '.') == "${i%%.*}". Also, you need to double quote both $i and $name, and probably use -e with grep just in case the filename read ($i) contains - as its first character (and use mv -- for the same reason). – Kusalananda May 25 '20 at 18:24
  • thanks @Kusalananda! I really learn from your comments and answers. – binarysta May 25 '20 at 18:26
  • Thank you both! I am going to try this . Just a curiosity: what will happen if the filename.csv contains also name of files wich are not present in this folder? Will they be skipped or cause an error? – ginopino May 25 '20 at 18:31
  • @ginopino it will be skipped, I'm editing to make it perfect and also adding some details. – binarysta May 25 '20 at 18:33
1

awk could be an option too, this one handle spaces in the name also.

file='filename.csv'
find_path='/home/kali/test/'
extension='.txt'

awk -v find_path=$find_path -v extension=$extension \
'/^$/{NR=--NR; next} \
/^.+/ {print "mv -f " "\"" find_path $0 extension "\" " \
"\"" find_path NR "_" $0 extension "\"" \
}' $file | sh
1

Assuming that you want to rename all files whose filename prefix is exactly a string in the CSV file, and that the filenames otherwise has a .txt filename suffix (and nothing else).

#!/bin/sh

suffix=txt

n=0
while IFS= read -r prefix; do
        n=$(( n + 1 ))

        name=$prefix.$suffix
        [ ! -e "$name" ] && [ ! -L "$name" ] && continue

        mv -- "$name" "${n}_$name"
done <filename.csv

This reads a line from the CSV into the variable prefix in each iteration of the while loop, and renames the file whose name is $prefix.$suffix (with $suffix being the static string txt) to ${n}_$prefix.$suffix, where n is a variable whose value is a simple counter of how many lines have been read.

The mv command is only carried out if the source file exists.

No test is made for name collisions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.