web-dev-qa-db-ja.com

mv:シェルスクリプトでそのようなファイルまたはディレクトリをstatできません

一部のファイルを1つのフォルダーから別のフォルダーに移動するスクリプトを作成しましたが、次のエラーが発生しました。2つのフォルダーを確認したところ、1つのフォルダーにそのようなファイルがあり、別のフォルダーにはそのようなファイルがないことに気付きましたが、すべてのファイルに「mvそのようなファイルやディレクトリはありません。」

    mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/194.199.68.165_tcp.folder/data/*': No such file or directory
    mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/194.42.17.124_tcp.folder/data/*': No such file or directory
    mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/195.113.161.13_tcp.folder/data/*': No such file or directory
    mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/203.159.127.3_tcp.folder/data/*': No such file or directory
    mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/212.199.61.205_tcp.folder/data/*': No such file or directory
    mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/212.51.218.235_tcp.folder/data/*': No such file or directory
    mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/213.73.40.105_tcp.folder/data/*': No such file or directory
    mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/41.225.7.4_tcp.folder/data/*': No such file or directory
    mv: cannot stat `/home/esolve/project/capture/tcp_50x50/dest_folder/83.230.127.122_tcp.folder/data/*': No such file or directory
    [esolve@kitty tcp_50x50]$ ls /home/wgong/project/capture/tcp_50x50/dest_folder/194.199.68.165_tcp.folder/
    [esolve@kitty tcp_50x50]$ ls /home/wgong/project/capture/tcp_50x50/dest_folder/203.159.127.3_tcp.folder/data/
    129.88.70.226   132.187.230.1    138.96.116.22   155.185.54.250   192.38.109.144  193.136.227.163  193.175.135.61  195.113.161.13  83.230.127.122
    130.104.72.200  132.227.62.122   147.83.29.232   156.17.10.52     192.42.43.22    193.137.173.218  193.205.215.74  212.199.61.205
    131.130.69.164  132.252.152.194  148.81.140.193  157.181.175.249  192.43.193.71   193.144.21.131   193.226.19.30   212.51.218.235
    131.188.44.102  134.151.255.180  152.66.245.162  160.78.253.31    193.1.170.136   193.145.46.243   194.199.68.165  213.73.40.105
    131.254.208.10  138.48.3.203     152.81.47.4     192.114.4.3      193.136.166.56  193.166.160.98   194.42.17.124   41.225.7.4

スクリプトは:

    list=`ls dest_folder`
    cd dest_folder
    cwd=`pwd`
    for folder in $list;do
            mv ${cwd}/${folder}'/data/*' ${cwd}/${folder}
    done

私はそれを/home/esolve/project/capture/tcp_50x50/

20
misteryes
mv ${cwd}/${folder}'/data/*' ${cwd}/${folder}

そこで引用符(')を使用すると、シェルがグロビングを実行できなくなります。 *は文字どおりmvコマンドに渡されますが、示されたディレクトリで*というファイルが見つからないため、コマンドは失敗します。

これを次のように変更します。

mv "${cwd}/${folder}/data"/* "${cwd}/${folder}"

(スペースを含むディレクトリ名がある場合に問題を防ぐために二重引用符を使用してください。引用符の外側に*を入力してください。)

ただし、空のディレクトリのエラーは引き続き表示されます。 (同じ種類の理由:ファイルがパターンに一致するものを見つけられない場合、パターン自体を引数としてコマンドに渡します。)

26
Mat

コードにはいくつかの問題があります:

list=`ls dest_folder`

lsの出力を、末尾の改行文字なしで$listに格納しています。 lsは、改行文字で区切られたファイル名のリストを出力します。 newlineは、ファイル名と同じように有効な文字であるため、出力を確実に使用することはできません。たとえば、lsaを含むディレクトリのb出力は、a<newline>bという1つのファイルを含むディレクトリの出力と同じです。

 cd dest_folder

そのコマンドの失敗をチェックしていません。一般的に、コマンドの終了ステータスを確認する必要がありますが、cdの場合は特にそうです。残りのコマンドは、あなたが新しいディレクトリにいると想定しているので、そうでない場合は劇的な結果になる可能性があります。

cwd=`pwd`

POSIXシェルは$PWD変数で現在のディレクトリへの(1つの)パスをすでに維持しているため、ここでpwd </ code>を使用する必要はありません(特にコマンド置換では一般的な場合)パスから末尾の改行文字を削除します)。また、mvは相対パスを受け入れるため、絶対パスを作成する必要はありません。

for folder in $list;do

変数を引用符で囲まずに残すのは、シェルではsplit + glob演算子です。つまり、変数の内容が分割され($IFSで言及されている区切り文字で空白文字の特別なルールが適用されます)、その結果、各要素でワイルドカード文字が検索され、リストに展開できます。一致するファイルの。

ここでは、分割は必要ですが改行文字のみであり、グロビングは必要ないため、無効にする必要があります。

 IFS='
 '; set -f
 for folder in $list
   mv ${cwd}/${folder}'/data/*' ${cwd}/${folder}

この場合も、変数を引用符で囲まずに残すのはsplit + glob演算子です。ここではどちらも必要ないため、これらの変数を引用符で囲む必要があります。

すでに述べたように、ワイルドカードは引用符で囲まれていない場合にのみ展開されるため、引用符から*を移動する必要があります。以前にset -fを使用してグロビングを無効にした場合は、そのコマンドを呼び出す前にset +fを使用してグロビングを復元する必要があります。

それを書くより良い方法は:

cd dest_folder &&
  for folder in */;do
    mv -- "${folder}data/"* "$folder"
  done

ただし、いくつかのメモ:

  • これにより、隠しフォルダーが除外され、隠しファイルがdataフォルダーから移動されなくなります。
  • プロセスで上書きされるファイルをチェックしていません(mv-iオプションを追加することをお勧めします)。
  • */を使用すると、ループはdirectoriesのみになりますが、ディレクトリへのシンボリックリンクも含まれます。そうしたくない場合は、ループ内に[ -L "${folder%/}" ] && continueを追加する必要があります。
  • そこに非表示でないフォルダがない場合、*/はそれ自体に展開されるため、mvから*/data/*というファイルが見つからないというエラーメッセージが表示されます。同様に、どのフォルダーにも非表示でないファイルがない場合は、that-folder/data/*が存在しないというエラーメッセージが表示されます。
8