Reputation: 613
The files that come in have spaces, single quotes, brackets, square brackets etc.
I remove spaces and replace with dots with the following command
for file in *.mp4; do mv "$file" `echo $file | tr ' ' '.'` ; done
Then I remove special characters with the following command
rename -n 's/[^a-zA-Z0-9_-]//g' "$file"
But for some reason single quotes(') are still present in file names. Is there a way to have clean file names in one command?
Upvotes: 10
Views: 18837
Reputation: 1
To get rid of double quotes in file name use the mv command:
for file in *; do mv "$file" "${file/\"/}"; done
It should work for single quotes as well.
This will apply to all files in the folder (ie., for file in *; do
).
The syntax ${file/\"/}
means: Take all file names, search for "
(make sure to include the backslash) and then replace it with nothing. If you wanted to replace all quotes with an underscore for example, the line would be ${file/\"/_}
.
To get rid of single quotes run:
for file in *; do mv "$file" "${file/\'/}"; done
Hope this helps!
Upvotes: 0
Reputation: 189387
If you need to rename files recursively, i.e. rename all files in a directory tree starting from the current directory, you need to wrap the command in find
. Here is a simple version which works if you have Bash available.
find . -d -name "*'*" -exec bash -c $'for f; do
mv "$f" "${f//\\\047/}"; done' _ {} +
If you don't have Bash, you need something like
find . -d -name "*'*" -exec sh -c 'for f; do
mv "$f" "$(echo "$f" | tr -d \'\'')"; done' _ {} +
which is slightly more expensive because it runs an external tr
command for each file. (Also, the quoting here is mildly challenging, to get a literal single quote passed as the argument to tr
inside a shell script in single quotes.)
The -d
option to instruct find
to do a depth-first search is important because it prevents you from attempting to rename a file whose parent directory has been renamed slightly earlier, which would fail because the old path no longer exists under the original name.
(The newline in the middle of the command is just for improved legibility on small screens; you can make it a one-liner if you like.)
The wildcard "*'*"
targets all files with a single quote in them; if you only want to process "*'*.mp4"
or "*'*.mp4'"
then obviously use one (or both) of those wildcards instead. Here's how you can combine them:
find . -d \( -name "*'*.mp4" -o -name ""*'*.mp4" \) -exec ...
Upvotes: 0
Reputation: 1
IMPORTANT! This is easily overlooked if not anticipated: Files coming from a Windows machine that contain spaces are represented on Linux with a single quote at each end. These single quotes "ARE NOT PART OF THE FILE NAME"! This is a no no on Linux, so use this command to replace the single quotes with underscores in order to make the files "real/legitimate":
sudo rename "s/\ /_/g" * #Replaces spaces with underscores to convert to Unix/Linux-style "real" filenames
Don't laugh at this! It's surprising how often this sort of oversight happens and how much time is wasted trying to figure out why none of the so-called proven solutions work, although it seems they should! We seldom, or don't expect to see spaces in Linux filenames, and so the "paradigm / force of habit syndrome" prevents us from noticing them. Every computer person understands fighting syntax, but this is another, tangential concern, that we must keep in mind.
If something does not work, there is always a reason ... often one that should have been obvious!
Upvotes: -1
Reputation: 117
sed command is one of the option for your requirement.
for file in *.mp4 ; do echo ${file}|sed -e "s/ /./g" -e "s/[\[{\\']//g" ; done
Example:
$ for file in *.mp4 ; do echo $file; done
as {df [jk \'hj.mp4
as {df[jk \'hj.mp4
as {df[jk\'hj.mp4
as {df [jk \'.mp4
$
$ for file in *.mp4 ; do echo ${file}|sed -e "s/ /./g" -e "s/[\[{\\']//g" ; done
as.df.jk.hj.mp4
as.dfjk.hj.mp4
as.dfjkhj.mp4
as.df.jk..mp4
$
Upvotes: -1
Reputation: 329
In bash:
for file in *.mp4; do dest="${file//[[:space:]]/.}" && mv -i "$file" "${dest//[^[:alnum:]._-]/}"; done
Upvotes: 14