私は一連のzipファイルを繰り返し抽出し、特定のファイル名パターンと一致するファイルだけが別のフォルダに移動するスクリプトを作成しました。
スクリプト:
#!/bin/bash
ARCHIVE_FILEMASK="????-??-??_E_MDT_0_0.7z"
FILEMASK="?????????_?????_A_?_????????????????-?????????"
extractDir=/path/to/dir
dest=/path/to/dest
for f in ${ARCHIVE_FILEMASK}
do
7z e -aoa -o"${extractDir}" "$f"
if [ $? != 0 ]
then
mv "${extractDir}/${FILEMASK}".xml "$dest"
fi
done
スクリプトの実行中にエラーが発生しました:
mv: cannot stat `/path/to/dir/?????????_?????_A_?_????????????????-?????????.xml': No such file or directory
nullglobとextglobを開こうとしましたが、役に立ちませんでした。シェルから直接コマンドを実行すると、正常に実行されます。同様の質問がある他の投稿からの回答も役に立ちませんでした。
編集する:
Paweł Rumianがディレクトリ名のスペースに問題がある可能性があると述べた後、AVJのプロンプトを試み、コマンドset +x
の前にmv
。
結果:
+ mv '/path/to/dir/????????????????????????_A_?_????????????? ???????-??????????? ??.xml '/パス/to/dest
だから今、一重引用符を削除する必要があります。どうすればいいのかご存知ですか?
答え1
一般に、変数拡張の周りに二重引用符を使用することをお勧めします。$foo
外側の引用符は、「値を取得してfoo
スペースで除算し、各結果の単語が1つ以上のファイルと一致する場合はそれをワイルドカードパターンに拡張する」ことを意味するためです。foo
特に、変数にファイル名が含まれている場合は必要な値です。ただし、ここでは実際にファイル名を使用するときに拡張しようとしているので、引用符foo
で囲んで使用しないでください。別々のパターンのリスト。この変数の値にスペースがないため、ここでは何の違いもありません。"$foo"
ARCHIVE_FILEMASK
FILEMASK
変数f
とextractDir
インクルードファイル名があるため、二重引用符を保持する必要があります。
for f in ${ARCHIVE_FILEMASK}
do
if 7z e -aoa -o"${extractDir}" "$f"; then
mv "${extractDir}/"${FILEMASK}.xml "$dest"
fi
done
Bashを使用しているため、ワイルドカードパターンがファイルと一致しない場合は、shopt -s nullglob
ワイルドカードパターンを空のリストに展開するように呼び出すことができます。コマンドにソースファイルを渡さないと、"${extractDir}/"${FILEMASK}.xml
コマンドmv
はファイルの欠落について文句を言います。一致するものが1つ以上ある場合にのみ呼び出すことで問題を解決できます。
shopt -s nullglob
for f in ${ARCHIVE_FILEMASK}
do
if 7z e -aoa -o"${extractDir}" "$f"; then
matches=("${extractDir}/"${FILEMASK}.xml)
if ((${#matches[@]})); then
mv "${matches[@]}" "$dest"
fi
fi
done
1以上は通常表示されているものと同じですIFS
。
答え2
解決策は二重引用符を削除することです。これで、移動コマンドは次のようになります。
mv ${extractDir}/${FILEMASK}.xml "$dest"
答え3
これは、mvコマンドがソースファイルを見つけることができないためです。ソースファイル名には特殊文字やその他の内容を含めることができます。
配置してスクリプトを実行します。セット-xmvコマンドの前後に+ xを設定します。
スクリプトの実行中に実行される正確なコマンドが表示されます。シェルから直接コマンドを実行してこれを確認してください。
答え4
.7zファイルにはまったく同じファイル名の複数のインスタンスが含まれていますか?私の考えではそうではないようです。すべて同じ "$dest"ディレクトリに移動したためです。
mv
この場合、コマンドをループの外に置く方がよいでしょう。部分的には、mv
コマンド全体を1つだけ実行するためです(mv
.7zファイルごとに1つではありません)。しかし、ほとんどのファイルが1つ以上ある可能性が高いからです。あなたのパターンで。そして、変数の周りに二重引用符を保持できます。これは、ファイル名にシェルまたはグローブの重要な文字が含まれている場合は安全です。
単一のコマンドで多すぎるファイルを抽出する場合は、次のようにmv
使用できますfind
。
find "$extractDir" -name "$FILEMASK.xml" -exec mv {} "$dest/" +
とにかく使用する方が良いですfind
。どのくらいのファイルが抽出されるのかわからないので、防御プログラミングに役立ちます。また、一致するファイルが見つからない場合は何もしないという利点があるため、mv
ファイルが見つからないという不満はありません。