Change file names with find and iconv

血红的双手。 提交于 2019-12-01 04:54:33

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!