9

I tried to remove apostrophe from all files' names in the directory.

for i in *; do mv $i `echo $i | tr -d "'"`; done

After executing this command nothing is renamed.

Do you know what's wrong here?

2
  • What error message do you see? Do the names also contain spaces?
    – Mikel
    May 6, 2012 at 14:39
  • @Mikel There wasn't error message. Yes, the names contained spaces too.
    – xralf
    May 6, 2012 at 14:42

3 Answers 3

12

You could try something like this (bash):

shopt -s nullglob
for i in *\'* ; do mv -v "$i" "${i/\'/}" ; done

This uses shell string replacement. You probably don't want to glob files that don't have ' in them since the mv would fail. Without the nullglob option, the glob pattern itself would be passed to mv if there are no matching files.

6

Always put double quotes around variable substitutions $foo and command substitutions $(foo) (unless you know why you need to leave them out and why it's ok to do so).

for i in *; do mv "$i" "$(echo "$i" | tr -d "'")"; done

This will mostly work, with a few restrictions:

  • You'll get bad behavior or errors if a file name begins with -, because mv will interpret it as an option.
  • This does not affect files whose name begins with ..
  • With some setups, this will mangle backslashes in the echo command.
  • Newlines at the end of the name are lost.

In ksh93, bash and zsh, you can write this with less hassle using the ${VARIABLE//PATTERN/REPLACEMENT} construct. Adding -- to mv takes care of file names beginning with -. If you have file names beginning with ., add .* or .[^.]* ..?* after * as needed.

for i in *; do mv -- "$i" "${i//\'/}"; done

In zsh, you can use zmv:

zmv '(*)' "\${1//\\'/}"

Under Debian, Ubuntu and other derivatives, you can use the rename Perl script.

rename "s/'//g" *
3

I assume your problem is the file also had spaces in its name. I can't reproduce your error without it.

$ touch "file" "user's file"
$ for i in *; do mv $i `echo $i | tr -d "'"`; done
mv: `file1' and `file1' are the same file
mv: target `file' is not a directory

So the reason it's failing is the second message: target 'file' is not a directory.

When your for loop sees a file with a space, it runs this:

mv user's file users file

So it thinks you're specifying three files (user's, file, and users), and a directory to move those files into (file).

Proper quoting of both should solve your immediate problem

$ for i in ./*; do mv "$i" "$(echo "$i" | tr -d "'")"; done
2
  • 2
    @xralf Note that there were still missing quotes in Mikel's last snippet, that would mangle multiple spaces and wildcards in file names. May 7, 2012 at 1:51
  • 2
    I added ./* in my edit. This prevents file names like -option from being misinterpreted.
    – jw013
    May 7, 2012 at 5:59

You must log in to answer this question.

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