如何使用“查找”字符串和特殊字符?

如何使用“查找”字符串和特殊字符?

我正在尝试编写一些 bash shell 脚本(第一次)来执行一些连续操作(一些复制、加密、上传和简单的逻辑检查),并且我正在努力处理find正在返回的字符串,因为它们有特殊的字符/\*)'("和空格。

我已经看到了使用修复此问题的建议printf %q,但我无法找出正确的 bash 语法。

以下是我如何尝试更改字符串的摘录:

#!/bin/sh

find "/upload" -type f |
    while read -r path; do
        fixedpath=printf %q "$path"
        fixedpath=printf '%q' "$path"
        fixedpath=printf '%q' $path
        fixedpath=printf "%q" "$path"
        fixedpath="printf %q $path"
        fixedpath="printf '%q' $path"
        fixedpath=$(printf '%q' $path)
        echo $path >> list.txt
        echo $fixedpath >> list.txt
    done
exit 0

我还可以想到另外 6-12 种方法来编写该printf函数,但我想您已经明白了,我需要使用哪一种方法来返回有效路径,以便将其作为参数传递给其他命令?

我正在 Ubuntu 16 上工作。

答案1

不要解析 的输出find,特别是如果您期望奇怪而美妙的文件名。

相反,要么通过 执行您需要执行的命令-exec,要么在命令本身中嵌入脚本find

find /upload -type f -exec sh -c '
    for pathname do
        printf "Would do something with \"%s\" here...\n" "$pathname"
    done' sh {} +

显然,您也可以将嵌入脚本放入其自己的文件中:

#!/bin/sh

for pathname do
    printf 'Would do something with "%s" here...\n' "$pathname"
done

进而...

find /upload -type f -exec /path/to/script.sh {} +

有关此主题的进一步阅读:

答案2

请注意,使用#!/bin/sh(可能)会限制您使用 POSIX 规范,而不是bash.既然你提到bash你应该将 shebang 更改为#!/bin/bash.

这一页,特别是“其他示例”部分。如果您需要使用,我的首选方法find是:

#!/bin/bash

while IFS= read -r -d '' f; do
   echo "$f"
   # Other actions on "$f" here
done < <(find /upload -type f -print0)

exit

这将通过使用空分隔符安全地处理特殊字符。

或者,使用几个bashshell 选项和一个for循环更简单:

shopt -s nullglob globstar

for f in /upload/**; do
   [[ -f $f ]] || continue
   echo "$f"
   # Other actions on "$f" here
done

这将递归地查找/upload.请务必"$f"在这两种方法中引用。


答案3

*当执行以下行时,脚本失败(展开星号):

echo $path
echo $fixedpath

例子:

$ path='test *'
$ echo "$path"
test *

$ echo $path
test file 1 file2 A longer file in this directory Some_Other_file ......

解决方案? : 引用你的 var 扩展。

话虽如此,唯一可行的作业是(也引用它):

fixedpath=$(printf '%q' "$path")
echo "$path" >> list.txt
echo "$fixedpath" >> list.txt

但是从 find 的输出中读取是一个坏主意,它可能会以与不引用变量类似的方式失败。阅读该部分的其他答案,它们都很好。

相关内容