Learner
Learner

Reputation: 627

batch rename to change only single character

How to rename all the files in one directory to new name using the command mv. Directory have 1000s of files and requirement is to change the last character of each file name to some specific char. Example: files are

abc.txt
asdf.txt
zxc.txt
...
ab_.txt
asd.txt

it should change to

ab_.txt
asd_.txt
zx_.txt
...
ab_.txt
as_.txt

Upvotes: 3

Views: 3847

Answers (7)

toolkit
toolkit

Reputation: 50237

Find should be more efficient than for file in *.txt, which expands all of your 1000 files into a long list of command line parameters. Example (updated to use bash replacement approach):

find . \( -type d ! -name . -prune \) -o \( -name "*.txt" \) | while read file
do 
    mv $file ${file%%?.txt}_.txt
done

Upvotes: 1

Aaron Digulla
Aaron Digulla

Reputation: 328594

If all files end in ".txt", you can use mmv (Multiple Move) for that:

mmv "*[a-z].txt" "#1_.txt"

Plus: mmv will tell you when this generates a collision (in your example: abc.txt becomes ab_.txt which already exists) before any file is renamed.

Note that you must quote the file names, else the shell will expand the list before mmv sees it (but mmv will usually catch this mistake, too).

Upvotes: 2

Andy
Andy

Reputation: 3854

Is it a definite requirement that you use the mv command?
The perl rename utility was written for this sort of thing. It's standard for debian-based linux distributions, but according to this page it can be added really easily to any other.

If it's already there (or if you install it) you can do:

rename -v 's/.\.txt$/_\.txt/' *.txt

The page included above has some basic info on regex and things if it's needed.

Upvotes: 1

paxdiablo
paxdiablo

Reputation: 881403

You have to watch out for name collisions but this should work okay:

for i in *.txt ; do
    j=$(echo "$i" | sed 's/..txt$/_.txt/')
    echo mv \"$i\" \"$j\"
    #mv "$i" "$j"
done

after you uncomment the mv (I left it commented so you could see what it does safely). The quotes are for handling files with spaces (evil, vile things in my opinion :-).

Upvotes: 2

mouviciel
mouviciel

Reputation: 67829

If your files all have a .txt suffix, I suggest the following script:

for i in *.txt
do
    r=`basename $i .txt | sed 's/.$//'`
    mv $i ${r}_.txt
done

Upvotes: 1

Plutor
Plutor

Reputation: 2897

You can use bash's ${parameter%%word} operator thusly:

for FILE in *.txt; do
   mv $FILE ${FILE%%?.txt}_.txt
done

Upvotes: 0

Paul Tomblin
Paul Tomblin

Reputation: 182782

I'm not sure if this will work with thousands of files, but in bash:

for i in *.txt; do
   j=`echo $i |sed 's/.\.txt/_.txt/'`
   mv $i $j
done

Upvotes: 0

Related Questions