Avoid replacing spaces when renaming files
I'm trying to rename files like this:
for file in *;
do
mv -i "$file" "$(echo "$file" | sed -e 's/[^A-Za-z0-9._-]/_/g')";
done
But the sed
command replaces all spaces with _
.
How can I edit the sed
command to make it inlcude spaces along with the specified characters? I've tried using \s
but it does not work...
EDIT:
For example: the file trip: hill
, should be renamed: trip_ hill
, but the command above makes it trip__hill
.
Do not parse filenames with sed
! The output of echo "$file"
may not be reliable.
Use rename
. On 17.10 you need to install it first
sudo apt install rename
Then:
rename -n -- 's/[^-A-Za-z0-9_ .]/_/g' *
Notes
- remove
-n
after testing to actually rename the files -
--
end-of-options in case any file begins with-
-
[^-A-Za-z0-9_ .]
characters we do not want to replace - put-
first or last so it can't indicate a range (it is treated literally in these positions). - Spaces can be included in the class
-
.
is treated literally (in other regex contexts it stands for any character and needs to be escaped).
This also works in sed
:
$ echo 'trip: hill' | sed 's/[^-A-Za-z0-9 _.]/_/g'
trip_ hill
If I add a space to the end in your version, I get an error:
$ echo 'trip: hill' | sed -e 's/[^A-Za-z0-9._- ]/_/g'
sed: -e expression #1, char 22: Invalid range end
But with -
at the end, it works:
$ echo 'trip: hill' | sed -e 's/[^A-Za-z0-9._ -]/_/g'
trip_ hill
So perhaps the position of the hyphen caused your problem when you added the space. But the advice not to parse filenames stands!
You can also just use the shell, Bash's parameter expansion can do substitution:
for f in ./* ; do
mv "$f" "${f//[^-A-Za-z0-9._ ]/_}"
done
The double slash tells it to replace all matches, other than that, the syntax is straightforward.