Search code examples
bashrenamefile-rename

How to remove the last characters in a file name using Bash?


I have several .txt files in a folder, their names look as follows:

file1.txt
file2.txt
file2.txt_newfile.txt
file3.txt
file4.txt
file4.txt_newfile.txt
file5.txt_newfile.txt
...

I am trying to remove _newfile.txt from the file names. If the file is present, it should be overwritten by the new file (e.g. file2.txt will be replaced, but file5.txt will just be renamed).

Expected output:

file1.txt
file2.txt # this was file2.txt_newfile.txt
file3.txt
file4.txt # file4.txt_newfile.txt
file5.txt #file5.txt_newfile.txt
...

I tried the following code:

for i in $(find . -name "*_newfile.txt" -print); do 
mv -f "$file" "${file%????????????}"
done

However, I get the following error:

mv: rename  to : No such file or directory

What am I doing wrong and how can I rename these files?


Solution

  • You're populating variable i with find's output, but referencing variable file, which is undeclared, in mv invocation. So it expands to mv -f '' '', that's why you get a No such file or directory error.

    You better do that like this:

    find -type f -name '*_newfile.txt' -exec sh -c '
    for fname; do
      mv -- "$fname" "${fname%_newfile.txt}"
    done' _ {} +
    

    If these files are all in the same folder, you don't even need find, just a for loop will do the same:

    for fname in *_newfile.txt; do
      mv -- "$fname" "${fname%_newfile.txt}"
    done