Remove all spaces in file names in one shell line

The problem:

We have a software that regularly looks into an 'input' directory. If new files are found in this directory, the software imports the file, archives it, and deletes the copy in the input directory.

But, from time to time, a file with a space in its name is created in the 'input' directory, for instance file_XXXZZZ _05. When that happens, the import procedure goes into a loop, does not import anything, and let files accumulate in the input directory. Why are these files created with screwy names? We don't know, and the programmers insist their product is bug-free (of course!).

By the time we receive an alert, it's usually too late, and we have to scramble to find the files with spaces in their names and rename them one by one, while making angry users wait on the phone.

The solution:

Use the following shell one-liner:

ls | grep " " | while read -r file_name ; do mv -v "$file_name" `echo $file_name | tr -d ' '` ; done

The tricks here are numerous, please note the different quotes, as they are really important:

And here is the result on a Linux machine:

bash-3.1$ ls | grep " " | while read -r file_name ; do mv -v "$file_name" `echo $file_name | tr -d ' '` ; done
`file_XXXZZZ _05' -> `file_XXXZZZ_05'
`file_XXXZZZ _09' -> `file_XXXZZZ_09'
`file_XXXZZZ _10' -> `file_XXXZZZ_10'

Finally, stick this one line in a little script, and execute the script regularly through your crontab. Peace of mind!

I can't remember where I saw this exactly, but the script-fu was strong in this one: if you ever read this and recognize your one-liner, my hat off to you sir !

You can also use the one-liner above to mass-rename files in a directory.

For instance, I found myself with a large number of digital camera files to rename, and here is what I used to give these files a better name:

bash-3.1$ ls | grep "JPG" | while read -r file_name ; do mv -v "$file_name" `echo $file_name | sed -e s/SAM/LosAngeles/g`
 ; done   
`SAM_0224.JPG' -> `LosAngeles_0224.JPG'
`SAM_0225.JPG' -> `LosAngeles_0225.JPG'
`SAM_0226.JPG' -> `LosAngeles_0226.JPG'
`SAM_0227.JPG' -> `LosAngeles_0227.JPG'
`SAM_0230.JPG' -> `LosAngeles_0230.JPG'
`SAM_0233.JPG' -> `LosAngeles_0233.JPG'
`SAM_0234.JPG' -> `LosAngeles_0234.JPG'
`SAM_0236.JPG' -> `LosAngeles_0236.JPG'
`SAM_0237.JPG' -> `LosAngeles_0237.JPG'
`SAM_0238.JPG' -> `LosAngeles_0238.JPG'
`SAM_0239.JPG' -> `LosAngeles_0239.JPG'
`SAM_0240.JPG' -> `LosAngeles_0240.JPG'
`SAM_0241.JPG' -> `LosAngeles_0241.JPG'
`SAM_0242.JPG' -> `LosAngeles_0242.JPG'

But what about the file extension? There you go:

bash-3.1$ ls | grep "JPG" | while read -r file_name ; do mv -v "$file_name" `echo $file_name | sed -e s/JPG/jpg/g` ; done
`LosAngeles_0224.JPG' -> `LosAngeles_0224.jpg'
`LosAngeles_0225.JPG' -> `LosAngeles_0225.jpg'
`LosAngeles_0226.JPG' -> `LosAngeles_0226.jpg'
`LosAngeles_0227.JPG' -> `LosAngeles_0227.jpg'
`LosAngeles_0230.JPG' -> `LosAngeles_0230.jpg'
`LosAngeles_0233.JPG' -> `LosAngeles_0233.jpg'
`LosAngeles_0234.JPG' -> `LosAngeles_0234.jpg'
`LosAngeles_0236.JPG' -> `LosAngeles_0236.jpg'
`LosAngeles_0237.JPG' -> `LosAngeles_0237.jpg'
`LosAngeles_0238.JPG' -> `LosAngeles_0238.jpg'
`LosAngeles_0239.JPG' -> `LosAngeles_0239.jpg'
`LosAngeles_0240.JPG' -> `LosAngeles_0240.jpg'
`LosAngeles_0241.JPG' -> `LosAngeles_0241.jpg'
`LosAngeles_0242.JPG' -> `LosAngeles_0242.jpg'

Hint: you can also do the second operation with tr or by using a slightly different sed pattern. This is left as an exercice for the reader...