その中には複数のサブフォルダとファイルがあるフォルダがあります。サブフォルダの名前とサブフォルダ内のファイルのパターンを含むCSVファイルもあります。
私がしたいのは、デフォルトのフォルダ内のwhileループを使用してCSVファイルを読み込みますsed
。私はbash
Unixで次のシェルスクリプトを使います:
IFS=","
while read f1 f2
do
find $f2/ -name vcs*.pv -exec sed -i '/$f1/d' {} +
done > export.csv
間違い:
find: 'ap01\r/': No such file or directory.
CSVファイル:
S2AEC67X1,ap01
値を正しく読み込んでいますが、f2
残りは行いません。すべてのサブフォルダーと共に、デフォルトのディレクトリにCSVファイルを保存します。
答え1
これ:ap01\r
あることを示します。入力する文字列の後にapi01
。 CSVファイルから削除してみてください。
アップデート:@RomanPerekhrestのコメントも読んでください。ループ内でを>
aに変更する必要があります(実際にそうする必要がある場合)。<
while
使用サイクルwhile
ですが、それは完全に別の議論です! )。
答え2
この質問のコードと入力ファイルにはいくつかの問題があります。
入力ファイルの各行には、
\r
明らかに末尾のキャリッジリターン()があります。これは、WindowsコンピュータでヒットがDOSテキストファイルとして生成されたためです。これらのキャリッジリターンを削除する一般的な方法は、dos2unix
ファイルから実行することです。たとえば、質問を参照してください。"^M" とは何か、その修復方法は?すべての変数拡張は二重引用符で囲む必要があります。コマンドは、
$f2
引用符なしでディレクトリのパス名を使用します。スペースが含まれていると失敗します$f2
。一重引用符は、シェルが変数を拡張するのを防ぎます。これは
sed
、スクリプトがリテラル正規表現に一致する行を見つけることを意味します$f1
。この正規表現は行$
の終わりのみと一致し、行の終わりは一致しないため、絶対一致しません。次に、f1
同じ行に文字を含めます。。二重引用符でスクリプトを編集すると、シェルが呼び出す前に変数を拡張しますsed
。$f1
sed
パターンはオプションの引数でなけれ
vcs*.pv
ばなりませんが、引用符がないため、ワイルドカードパターンと一致する現在のディレクトリのすべての名前に展開されます。したがって、現在のディレクトリにという名前のファイルがある場合は、そのファイルが呼び出され、その名前のファイルのみが検索されます。現在のディレクトリに複数の一致する名前がある場合は、不明なオプションについて文句を言うことができます。-name
find
vcs-test.pv
find
-name vcs-test.pv
find
ファイル
export.csv
は出力されます(ループ内で出力が発生する前に空になります)。何度も何度も読もうと思うかもしれません。これに>
はに変更することが含まれます<
。
スクリプトが修正されました:
while IFS=',' read f1 f2; do
find "$f2" -type f -name 'vcs*.pv' -exec sed -i "/$f1/d" {} +
done <export.csv
誤ってディレクトリ名を取得したくないので、コマンドライン-type f
にも追加しました。私はまた変数を設定find
するためにこれをしましたIFS
ただコマンドのためにread
。
これはすべてのファイルが配置されている上記のバリエーションです。まっすぐCSVファイルから名前を読み取った最上位ディレクトリの下:
while IFS=',' read dir pattern; do
for name in "$dir"/vcs*.pv; do
test -f "$name" && sed -i "s/$pattern/d" "$name"
done
done <export.csv
これの利点は、あなたがそれを避けることができるということですfind
。欠点は、sed
ファイルごとに1回呼び出す必要があることです(通常、何百ものファイルがないと問題になりません)。
以下は、上記のバリエーションで行を削除します。ひもCSVファイルから読み込みます。違いは、上記のコードスニペットがパターンを次のように解釈することです。正規表現、固定文字列ではありません。文字列に正規表現(たとえば、など)で「特殊」と解釈される文字が含まれている場合、.
これは*
重要[
です。]
while IFS=',' read dir string; do
for name in "$dir"/vcs*.pv; do
[ ! -f "$name" ] && continue
grep -v -F -e "$string" "$name" >"$name.tmp" && mv -f "$name.tmp" "$name"
done
done <export.csv