我正在尝试编写一些 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
这将通过使用空分隔符安全地处理特殊字符。
或者,使用几个bash
shell 选项和一个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 的输出中读取是一个坏主意,它可能会以与不引用变量类似的方式失败。阅读该部分的其他答案,它们都很好。