一部のシーケンシャル操作(一部のコピー、暗号化、アップロード、および単純な論理チェック)を実行するために(最初に)bashシェルスクリプトを作成しようとしたときに返される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
null 区切り文字を使用して特殊文字を安全に処理します。
または、いくつかのbash
シェルオプションとループを使用する方が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の出力を読むのは悪い考えです。変数を引用しないのと同じ方法で失敗することがあります。このセクションの他の答えを読んでください。すべて良いです。