如何用bash脚本替换引号


2

我有这个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脚本中输出输出时,我想自动重命名所有文件名。但单引号会产生问题。

非常感谢任何建议。沃尔特

编辑:这是完成我的chekc NTFS for Filename脚本。

     #!/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

我已经添加了另一个答案,不是为了减损virtex,这是正确的,而是指出更短,更有效的方法来做到这一点。就是这样。
MariusMatutiae 2016年

Answers:


0

如果您将文件名放在刻度线之间,则使用反斜杠转义字符将不起作用。还有另一种方法可以做到这一点。这是我过去使用的一个可能对你有用的引用函数。

#
# 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

并且在执行时成功重命名了该文件。


0

Virtex的答案当然是完全正确的。我只是想指出的是,这种操作是更容易开展猛砸数组:只是要清楚,让我们假设我们希望剥离初始字符./找到的文件名的叶子在这个简单的命令:

find -maxdepth 1 -type f

这可以按如下方式完成:

#!/bin/bash

declare -a mylist
mylist=(`find -maxdepth 1 -type f `)
mylist=(${mylist[@]/\.\//})
echo "${mylist[@]}"

人们希望通过逐个修改数组元素来对数组进行Bash搜索和替换。这可以修改为包含您的示例。

编辑

如果我有数百万个文件怎么办?

一千万?

$ 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

谢谢马吕斯,但如果我有数百万个文件怎么办?bash阵列会有RAM内存限制吗?
Walter Schrabmair 2016年

@WalterSchrabmair请看我的编辑。
MariusMatutiae 2016年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.