views:

333

answers:

7

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
A: 

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
Paul Tomblin
A: 

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
mouviciel
This doesn't look as if it replaces the letter before the period with the underscore.
unwind
I didn't actually know basename could do that (thanks for the education), but the solution is flawed - it adds the underscore rather than replacing the last character.
paxdiablo
Yes, you're right. I edit by intentionally keeping basename.
mouviciel
+2  A: 

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 :-).

paxdiablo
A: 

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

for FILE in *.txt; do
   mv $FILE ${FILE%%?.txt}_.txt
done
Plutor
+1  A: 

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
toolkit
+1  A: 

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.

Andy
+1  A: 

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).

Aaron Digulla