那个“不可打印”字符叫什么,这样我就可以使用正确的术语来查找或询问如何删除该字符以重命名我的文件,在不使用 BASH 脚本删除任何其他格式化字符的情况下删除它?
这是我正在使用的脚本,但我没有得到想要的结果。
#!/bin/bash
typeset -i count
let count=0
working_dir="/home/userx/temp/"
script_dir="/home/userx/temp/"
MAXFILES="$(find "$working_dir" -type f | wc -l)"
find "$working_dir" -type f | while [[ $count -ne '3' ]] ;
do read FILENAME;
w=$FILENAME
xpath=${w%/*}
xbase=${w##*/}
xfext=${xbase##*.}
xpref=${xbase%.*}
path=${xpath}
pref=${xpref}
ext=${xfext}
echo "extions is : $ext" echo
if [[ "$ext" == 'mp3' ]] ; then
echo "$ext" echo
pref=$(tr -dc '[[:print:]]' <<< "$pref")
## holds on to normal chars rids the rest
# pref=${pref//[^A-Za-z&0-9 ]/ }
echo "new title is -> $pref"
sleep 2
#file=${FILENAME##*/}
# Newfile=${file%_*}
# echo " mv -v "$working_dir"/"$file" "$working_dir"/"$Newfile" "
(( count++ ))
fi
done
结果是这样的
[userx@voided temp]$ ./Justrenamefiles
max file is : 311
FILENAME IS: /home/userx/temp/Joy Division - Ceremony (Graveyard Studios, Prestwich - Previously
extions is : Joy Division - Ceremony (Graveyard Studios, Prestwich - Previously echo
FILENAME IS: unreleased).mp3
extions is : mp3
**new title is -> unreleased)**
正如您所看到的,它删除了太多的文件名。尝试脚本中的两种方法,一种现在已被注释掉,我仍然没有得到我想要的结果。
有谁知道我可以使用什么代码片段来获得我想要的结果?
答案1
该图形表示 Unicode 值为 000A(十六进制)的字符。这是换行(LF)字符,即换行符。
Linux 允许在文件名中使用换行符,但这种情况非常不寻常。可以在 shell 脚本中处理带换行符的文件名,但需要特别小心。您的脚本解析 的输出find
,并且由于此输出使用换行符来分隔项目,因此此方法本质上无法处理文件名中的换行符。
您的脚本比需要的要复杂得多。如果你让事情变得简单,它就会起作用。作为一般规则,在拥有数据时对其进行操作,而不是将所有内容打包到文本流中并再次解析它。
使用 时find
,不解析输出。使用-exec
动作。
进行此重命名的最简单方法(我将用空格替换换行符)是桀骜,得益于其zmv
功能。
autoload -U zmv # put this in your .zshrc
cd $working_dir
zmv '**/*' $'${f//\n/ }'
如果您确实需要坚持使用始终预装在非嵌入式 Linux 上的程序,这里有一个简单(虽然有点慢)的方法,它依赖 bash 来进行重命名:
find "$working_dir" -type f -name '*
*' -exec bash -c 'mv "$0" "${0//
/ }"' {} \;
您可以通过对批量文件调用 bash 来加快速度:
find "$working_dir" -type f -name '
' -exec bash -c 'for x; do mv "$x" "${x//
/ }"' _ {} +
如果在 Linux 上只有一个换行符,您可以使用rename
命令(rename.ul
在 Debian 及其衍生版本上调用)。
find "$working_dir" -type f -name '
' -exec rename '
' ' ' {} +
如果你有prename
:
find "$working_dir" -type f -name '
' -exec prename 'y/\n/ /' {} +
答案2
问题是您的文件名包含换行符,例如aaa\nbbb
,并且您的find | read
方法无法区分它与两个文件aaa
和bbb
。
通常的答案是使用find
nul 字符来获取单独的文件名,然后使用读取此输入流。告诉read 使用 nul 字符作为行分隔符,停止反斜杠处理,并在开始和结束处保留空格。\0
find -print0
IFS= read -r -d '' FILENAME
-d ''
-r
IFS=