我有这个 bash 脚本
#!/bin/bash
find . -type f > /home/wschrabi/filenames
while read filename; do
stripped="$(printf '%s\n' "$filename" | tr -d -C '[[:alnum:]][[:space:]][!\"\#\$\%\&\(\)\*\+\,\-\.\/\:\;\<\=\>\?\@\[\\\]\^\_`{|}~]')";
ohne="$(sed -e 's/[\d126-\d255\"*:<>\?\\\|]/_/g' <<<$filename)";
test "$filename" = "$stripped" || printf "mv '%s' '%s'\n " "${filename//[\']/'\\''}" "${ohne//[\'\"\`]/_}";
done < /home/wschrabi/filenames
并且${filename//[\']/'\\''}
我想在文件名中替换单引号。目的应该是当我在 bash 脚本中管道输出时,我想自动重命名所有文件名。但单引号会带来问题。
非常感谢你的建议。Walter
编辑:这里是为了完成我的 chekc NTFS 文件名脚本。
#!/bin/bash
#
# Quote a string, wrapping it in tick marks ('), and escaping any
# embedded ticks.
#
# Inputs:
# $1: The string to quote
#
# Returns:
# (stdout) - The quoted string
#
quote() {
if [ $(echo "$@" | tr -d "\n" | wc -c) -eq 0 ]; then
echo "''"
elif [ $(echo "$@" | tr -d "[a-z][A-Z][0-9]:,.=~_/\n-" | wc -c) -gt 0 ]; then
echo "$@" | sed -e "s/'/\'\"\'\"\'/g" | sed -e "s/^/'/g" -e "s/$/'/g"
else
echo "$@"
fi
}
if [ $# -eq 0 ]
then echo "No arguments supplied: USAGE: checkNTFS_filenames.sh <file_to_check>"
fi
if [ $# -eq 1 ]
then
#find . -type f > /home/wschrabi/filenames2
while read filename; do
stripped="$(printf '%s\n' "$filename" | tr -d '\"\*\:\<\>\?\\\|')";
ohne="$(sed -e 's/[\d126-\d255\"*:<>\?\\\|]/_/g' <<<$filename)";
if [ "$filename" != "$stripped" ] ;
then printf "mv %s %s\n" "$(quote "$filename")" "$(quote "$stripped")"
fi
done < $1
fi
答案1
如果您将文件名放在刻度线之间,则使用反斜杠转义字符将不起作用。不过,还有另一种方法可以做到这一点。这是我过去使用过的引用功能,可能对您有用。
#
# Quote a string, wrapping it in tick marks ('), and escaping any
# embedded ticks.
#
# Inputs:
# $1: The string to quote
#
# Returns:
# (stdout) - The quoted string
#
quote() {
if [ $(echo "$@" | tr -d "\n" | wc -c) -eq 0 ]; then
echo "''"
elif [ $(echo "$@" | tr -d "[a-z][A-Z][0-9]:,.=~_/\n-" | wc -c) -gt 0 ]; then
echo "$@" | sed -e "s/'/\'\"\'\"\'/g" | sed -e "s/^/'/g" -e "s/$/'/g"
else
echo "$@"
fi
}
当你运行它时,你会得到类似这样的输出。
$ quote abc
abc
$ quote "abc'def"
'abc'"'"'def'
$ quote \"abc\"
'"abc"'
$ quote "abc def"
'abc def'
这里的想法是,您可以用以下命令替换脚本中的最后一个 printf:
printf "mv %s %s\n" "$(quote "$filename")" "$(quote "$ohne")"
使用文件名为 abc'def 的脚本并进行上述更改后,我得到了此输出。
mv 'abc'"'"'def' abcdef
并且在执行时成功重命名文件。
答案2
Virtex 的回答当然是完全正确的。我只想指出,这种操作更容易用Bash 数组:为了清楚起见,我们假设我们希望删除初始字符./哪个寻找在这个简单的命令中保留文件名:
find -maxdepth 1 -type f
可以按照如下方式完成:
#!/bin/bash
declare -a mylist
mylist=(`find -maxdepth 1 -type f `)
mylist=(${mylist[@]/\.\//})
echo "${mylist[@]}"
Bash 搜索和替换按照人们希望的方式对数组进行操作:逐个修改数组元素。可以对其进行修改以包含您的示例。
编辑:
如果我有数百万个文件怎么办?
1000万怎么样?
$ time /bin/bash -c 'unset array && declare -a array && array=($(seq 1 10000000)) && echo "${array[6]}"; unset array'
7
real 0m11.110s
user 0m10.412s
sys 0m0.724s
$ inxi -C
CPU: Dual core Intel Core i7-5500U (-HT-MCP-) cache: 4096 KB
clock speeds: max: 3000 MHz 1: 2509 MHz 2: 2471 MHz 3: 2631 MHz 4: 2471 MHz