19

How can I rename all the files in a specific directory where the files contains blanks spaces and special characters ($ and @) in their names?

I tried the rename command as follows to replace all the spaces and special characters with a _:

$ ls -lrt
total 464
-rwxr-xr-x. 1 pmautoamtion pmautoamtion 471106 Jul 17 13:14 Bharti Blocked TRX Report [email protected]


$ rename -n 's/ |\$|@/_/g' *
$ ls -lrt
total 464
-rwxr-xr-x. 1 pmautoamtion pmautoamtion 471106 Jul 17 13:14 Bharti Blocked TRX Report [email protected]
$

The command works, but won't make any changes in the file names and won't return any error either. How can in fix this and are there other ways as well?

3
  • 2
    You may be expecting the perl rename script (ref: manpages.ubuntu.com/manpages/dapper/man1/prename.1.html) but are instead getting util-linux rename, which does not work the same way.
    – Jeff Schaller
    Commented Jul 17, 2015 at 16:54
  • rename command has many versions depending on OS. My Centos rename is <code> rename [options] expression replacement file... </code> Commented Jun 26, 2022 at 17:14
  • @Jeff Schaller - I was using the linux version on a fedora box but needed to do some work on a unbutu box and got confused. The which & file cmds sorted things out and the man page triggered a lot of 1990s memories.
    – Jim
    Commented May 22 at 13:23

8 Answers 8

14

The -n flag is for

--no-act

No Action: show what files would have been renamed.

So it's normal if you don't have any changes.

Regarding your command, it's working for me:

$ touch "a @ test"
$ ls
a @ test
$ rename -n 's/ |\$|@/_/g' *
a @ test renamed as a___test

Maybe depending on your shell, you have to escape the |

$ rename -n 's/ \|\$\|@/_/g' *

Or you can use the […] notation to group characters:

$ rename -n 's/[ @\$]/_/g' *
5
  • 1
    I tried all the three without -n option and still it won't change the name of the file. I doesn't give any error for any of the 3 types mentioned above. Maybe the rename command doesn't work for some reason. Is there any other way to change all the files in a directory with spaces or $ or @ in their names? Commented Jul 17, 2015 at 8:12
  • @AnkitVashistha does rename -n 's/./_/g' * outputs something? Commented Jul 17, 2015 at 8:22
  • It doesn't give anything, no output, no error. It just lands on next command line. Commented Jul 24, 2015 at 9:59
  • rename is also not working for me to replace (space) or ':' on Ubuntu 18.04, Bash 4.4.20(1)-release
    – Ouss
    Commented Feb 14, 2020 at 11:42
  • all these years and never knew of rename - awesome!
    – Goblinhack
    Commented Mar 21, 2023 at 20:08
10

You could try like this:

for file in ./*Block*                                       
do echo mv "$file" "${file//[ ()@$]/_}"
done

If you're happy with the result, remove the echo before mv to actually rename the files.

0
4

looking for a handsome script to remove special characters as well as german special characters, replacing them with universal ones to not remove useful information I've updated the last version of the script which had some minor issues resulting in:

#!/bin/bash

for file in ./*
do
  infile=`echo "${file:2}"|sed  \
         -e 's|"\"|"\\"|g' \
         -e 's| |\ |g' -e 's|!|\!|g' \
         -e 's|@|\@|g' -e 's|*|\*|g' \
         -e 's|&|\&|g' -e 's|]|\]|g' \
         -e 's|}|\}|g' -e 's|"|\"|g' \
         -e 's|,|\,|g' -e 's|?|\?|g' \
         -e 's|=|\=|g'  `
  outfileNOSPECIALS=`echo "${file:2}"|sed -e 's|[^A-Za-z0-9._-]|_|g'`
  outfileNOoe=`echo $outfileNOSPECIALS| sed -e 's|ö|oe|g'`
  outfileNOae=`echo $outfileNOoe| sed -e 's|ä|ae|g'`
  outfileNOue=`echo $outfileNOae| sed -e 's|ü|ue|g'`
  outfileNOOE=`echo $outfileNOue| sed -e 's|Ö|OE|g'`
  outfileNOAE=`echo $outfileNOOE| sed -e 's|Ä|AE|g'`
  outfileNOUE=`echo $outfileNOAE| sed -e 's|Ü|UE|g'`
  outfileNOss=`echo $outfileNOUE| sed -e 's|ß|ss|g'`
  outfile=${outfileNOss}
  if [ "$infile" != "${outfile}" ]
  then
        echo "filename changed for " $infile " in " $outfile
        mv "$infile" ${outfile}
  fi
done

exit

resulting in:

enter image description here

@don_crissti: He's doing the hokus-pokus with the infile since linux would have it's own issues with handling special characters when moving the filename.

4
  • 1
    special characters ? which ones ? Commented Feb 22, 2017 at 0:00
  • Space, At symbol, Ampersand .... Commented Feb 22, 2017 at 7:38
  • There is no problem moving a file with a name which contains special characters (including a newline)... You're probably not familiar with the shells (and btw, this has nothing to do with linux, it's a shell feature...) Commented Feb 22, 2017 at 17:42
  • mh okay - you're maybe right Commented Feb 23, 2017 at 12:28
2

There is a very handy tool called detox that will do exactly this transformation/renaming for you.

You can pass it a directory name (eventually recursing) or a pattern of specific files:

detox ./

or

detox *.csv

Here is how the transformation is done on the example you gave ("Bharti Blocked TRX Report [email protected]")

ls *.csv
Bharti_Blocked_TRX_Report_Morning_20150716.csv

This package is bundle with most Linux distributions.

1
  • 2
    Try first with dry run with -n Commented Apr 10 at 10:49
1

Since the rename command didn't work for me for unknown reasons and i do not get any other answers for my question, i myself tried to make an effort to make the rename possible. This might not be the best approach to rename the files but it worked for me and this is why i would like to post it as an answer so that if anyone else reads this might get some help to change the file names the way i did.

Now for me, i know that all the files will have a specific text in their names which is the word "Block". Following are the file names before their renaming was done:

anks@anks:~/anks$ ls -lrt
total 4
-rw-r--r-- 1 anks anks   0 Jul 25 14:47 Bharti TRX Block [email protected]
-rw-r--r-- 1 anks anks   0 Jul 25 14:47 Bharti TRX Block [email protected]
-rw-r--r-- 1 anks anks   0 Jul 25 14:47 Bharti TRX Block [email protected]
-rw-r--r-- 1 anks anks   0 Jul 25 14:47 Bharti TRX Block [email protected]
-rw-r--r-- 1 anks anks   0 Jul 25 14:48 Bharti TRX Block [email protected]

Now i have written a small shell script to make this possible. Following is the code:

#!/bin/bash

PATH="/home/ebfijjk/anks"

# Put the old filenames in a file.
ls $PATH | grep Block >> oldValues

# Put the new names without " " or "@" or "$" in another file
cat oldValues | sed 's/\$/_/g' | sed 's/\@/_/g' | sed 's/ /_/g' >> newValues

# Create a new file with Old names and New names seperated by a #.
paste -d'#' oldValues newValues >> oldAndNew

# Read the file with both old and new names and rename them with the new names.
while IFS='#'; read oldValue newValue
do
    mv "$oldValue" "$newValue"

done < oldAndNew

rm oldValues newValues oldandNew

And that's it, when i run the script, it renames all the file names having blank spaces () or $ or @ with _ instead of these characters.

3
  • you can replace cat foo | sed S1 | sed S2 | sed S3 >> bar by sed -e S1 -e S2 -e S3 foo >> bar
    – Archemar
    Commented Jul 25, 2015 at 15:17
  • 2
    @Archemar - or simply sed 's/[ ()@$]/_/g' or sed 'y/ ()@$/_____/' Commented Jul 25, 2015 at 16:17
  • Thank you don_crissti and Archemar for your comments and suggestions. Commented Sep 13, 2016 at 7:47
1

I have been looking for a solution to this problem for a while now. I work on old closed systems that can't have new packages installed. I don't have the rename command. Finally I wrote a script that appears to work with all keyboard entered special characters. ~@#$%^&*()-_=+[]{}\|;:",<.>?' The script will rename every file and directory in the current directory. It will replace all special characters,except -_. with the _ character. The outfile= line can be modified to use a different character for replacement if desired. Replace |_| with |.| to use the . character for example.

#!/bin/bash

for file in ./*
do
  infile=`echo "${file:2}"|sed  \
         -e 's|"\"|"\\"|g' \
         -e 's| |\ |g' -e 's|!|\!|g' \
         -e 's|@|\@|g' -e 's|*|\*|g' \
         -e 's|&|\&|g' -e 's|]|\]|g' \
         -e 's|}|\}|g' -e 's|"|\"|g' \
         -e 's|,|\,|g' -e 's|?|\?|g' \
         -e 's|=|\=|g'  `
  outfile=`echo "${file:2}"|sed -e 's|[^A-Za-z0-9._-]|_|g'`
  mv "$infile" ${outfile} &
done

exit
0
1

This one just strip the special characters from filenames

for file in *; do mv "$file" `echo $file | tr -cd '.A-Za-z0-9_-'` ; done
ॐNámásté Egész-ség.mkv --> NmstEgsz-sg.mkv

put echo after ; do to test before, like:

for file in *; do echo mv "$file" `echo $file | tr -cd '.A-Za-z0-9_-'` ; done

Another solution:

rename -v 's/[^a-zA-Z0-9\.\s_-]//g' *.* && rename -v 's/[\s]/_/g' *.*
ॐNámásté Egész-ség.mkv --> Nmst_Egsz-sg.mkv

-n option to test before.

0

For me on Ubuntu 18.04 LTS with bash 4.4.20(1)-release this one-liner worked well to remove spaces, @, : #...

To test (note the echo command:

for file in ./* ; do if [[ $file == *['!'\ :@#]* ]]; then echo mv "$file" "${file//[ #()@$:]/_}"; fi; done

To execute:

for file in ./* ; do if [[ $file == *['!'\ :@#]* ]]; then echo mv "$file" "${file//[ #()@$:]/_}"; fi; done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .