コードが期待どおりに動作しなかった直接の理由をすでに発見しました:ls
からのエラー stderr に報告され (POSIX で提案されているように)、パイプによって入力としてキャプチャされません。したがって、通常の出力の混合物が得られます (sed
によって変更されずに渡されます)。 ステートメント) および stderr (それらをバイパスします)。 ls
の理由がわかりません 呼び出し間で出力が変更されました。 stdout を /dev/null にリダイレクトすると、出力からすべての「通常の」(既存のパス) が削除されるはずです。これに対する修正はありません ただし、stderr を stdout に押し込むためです。
ls
からの出力の後処理 信頼できるスクリプトが必要な場合、危険な考えです。このトピックに関する 1 つの優れた記事は、wooledge.org サイトで入手できる「Why you should not parse the output of ls(1)」です。 Unix &Linux サイトの 1 つの詳細な Q/A では、いくつかの問題について説明しています。 ls
を解析します (代わりに何をすべきか)?つまり、UNIX ファイル名には、スペース、タブ、改行、一重引用符、二重引用符、エスケープされた一重引用符など、ほぼすべての文字を含めることができます。簡単な例として、次の名前のディレクトリを考えてみましょう。これらはすべて完全に合法です:
- "そのようなファイルはありません" (
mkdir "No such file"
) - "ls:'foo' にアクセスできません:そのようなファイルまたはディレクトリはありません" (
mkdir "ls: cannot access 'foo': No such file or directory"
) -
"ディレクトリ
と
埋め込み
改行" (
mkdir $'directory\nwith\nembedded\newlines'
)
1 つ目は、grep
によって (stdout から) 誤ってキャプチャされた無実のディレクトリです。 . 2 つ目も誤ってキャプチャされますが、完全に異なるパスにさらに混乱します。 -- 存在する場合と存在しない場合があります。 -- sed
によって ステートメント。 3 つ目は、ls
の出力を渡すとどうなるかの一例です。 行指向のプログラムに。ディレクトリが存在しない場合、ls
複数の行でそう言うでしょう、それはおそらくあなたが2つの別々の sed
になった方法です
"良いパス" (存在し、読み取り可能なもの) と "悪いパス" を区別するために、配列をループして、それぞれの新しい配列を作成することをお勧めします。
for p in "${paths[@]}"
do
if [ -r "$p" ]
then
goodpaths+=("$p")
else
badpaths+=("$p")
fi
done
その後、各セットで好きなことを行うことができます:
printf 'Good path: -->%s<--\n' "${goodpaths[@]}"
echo
printf 'Bad path: -->%s<--\n' "${badpaths[@]}"