The easy way is with zsh. Zsh is part of the base OS X installation but needs to be installed through the package manager on most Linux distributions and installed from ports on *BSD. Zsh provides the zmv
function which makes many file renaming tasks easy. First run this (or put it in your .zshrc
, for interactive use):
autoload zmv
Then you can use either
zmv '(**/)(*)' '$1${2//[^A-Za-z0-9]/_}'
or the equivalent
zmv '**/*' '$f:h${${f:t}//[^A-Za-z0-9]/_}'
The first zmv
command renames all files matching **/*
(i.e. all files in the current directory and in subdirectories recursively), into files in the same directory ($1
) and with the base name transformed to replace every character matching [^A-Za-z0-9]
by a _
. The parentheses in (**/)(*)
cause the directory part of the path (everything up to the last /
) to be assigned to $1
and the base name of the file to $2
. The second command does the same, but uses $f
to refer to the whole original name and the modifiers :h
and :t
to extract the directory and base parts of the name.
Your script breaks on all kinds of ways because it runs various special characters through their shell handling instead of treating them literally. To understand why, read Why does my shell script choke on whitespace or other special characters?
awk
/sed
for the charter replacement and some form offind
command to find all the files you need to process. How you use the pipes to make it the easiest way for you, is taotally up to you – MelBurslan Mar 23 '16 at 17:12file_clean=$(echo "file" | tr -dc '[:alnum:].')
– Jeff Schaller Mar 23 '16 at 17:24