问题
I've tried to change filenames using following script:
find dir/ -type f -exec mv {} $(echo {} | iconv -f UTF8 -t ASCII//TRANSLIT ) \;
Why doesn't it work? I mean when I have a file with character like 'ą' it should convert it to 'a'.
$ echo ążźćó | iconv -f UTF8 -t ASCII//TRANSLIT
azzco
why does it not work in find -exec?
$ find dir/ -type f -exec mv {} $(echo {} | iconv -f UTF8 -t ASCII//TRANSLIT ) \;
mv: `dir/zią' and `dir/zią' are the same file
I get the same results using xargs:
$ find dir/ -type f | xargs -I{} echo {} | iconv -f UTF8 -t ASCII//TRANSLIT
dir/zia
but:
$ find dir/ -type f | xargs -I{} mv {} $(echo {} | iconv -f UTF8 -t ASCII//TRANSLIT)
mv: `dir/zią' and `dir/zią' are the same file
回答1:
The problem with using $()
in this way is that the subshell executes prior to executing the find
command, and not as part of -exec
. You can do it, but you'll need to invoke bash. Something like:
find dir/ -type f -exec bash -c 'mv "$1" "$(iconv -f UTF8 -t ASCII//TRANSLIT <<< $1)"' -- {} \;
Keep in mind this will also translit any special chars in directory names as well, which may cause the mv
to fail. If you only want to translit the filename, then you could:
find dir/ -type f -exec bash -c 'mv "$1" "${1%/*}/$(iconv -f UTF8 -t ASCII//TRANSLIT <<< ${1##*/})"' -- {} \;
which split the directory portion off and only translits the file name.
回答2:
I don't know iconv that well, but
echo ... | iconv ....
is fine for text strings, but if you want you use a filename, certainly you need to specify the file on the right-hand-side of the iconv command line, i.e.
ls *.files | xargs -I{} iconv -f UTF8 -t ASCII//TRANSLIT {}
right?
As for moving (mv
) a file, you have make sure that the source filename is different from the target filename. It's not clear from you post what you want the target filename to be. If iconv
can modify files in-place AND you don't care to keep the original, then I would expect the xargs I provide above should solve your problem.
OR are you saying that the actual filenames contains characters that you want to process with iconv
. It might help to edit your post to include sample filenames, before and after iconv processing. Something like this?
find dir/ -type f -exec mv {} $(echo {}.fix | iconv -f UTF8 -t ASCII//TRANSLIT ) \;
For filenames that don't get modified by iconv
, you have to have a way to make the name separate from the original filename. So this would be followed by an /bin/rm {}
step.
OR see this post How to recursively convert all filenames in folder subtree from UTF-8 to ASCII in Linux .
I hope this helps.
回答3:
This should also work:
#!/bin/bash
if [ "$1" = "DO" ] ; then
if [ "$2" != "$3" ]; then
mv "$2" "$3";
fi
else
find dir/ -type f -exec "bash" $0 "DO" {} $(echo {} | iconv -f UTF8 -t ASCII//TRANSLIT ) \;
fi
来源:https://stackoverflow.com/questions/9930484/change-file-names-with-find-and-iconv