*を使用したXargsとrm

*を使用したXargsとrm

次のコマンドを実行しようとしています。

ls -d a* | xargs -i sudo rm -rf {}/*

問題は、そのセクションを追加する/*とコマンドが機能しないことです。ディレクトリの内容(ディレクトリ自体ではない)を削除したいと思います。

答え1

何についてrm -r a*/*?これにより問題が解決します。

答え2

このようなコマンドはrmワイルドカードを拡張するためにシェルを使用するため、どこかでシェルを呼び出す必要があります。

おそらく

 ls -d a* | xargs -i sh -c sudo rm -rf {}/*

答え3

警告する:まだこのコマンドをテストしていません。オタナエラーがある可能性があります。echoorとnoを最初に使用してすべてをls試してくださいsudo。 )

一般的なアドバイス:xargs何かをする最も簡単な方法はほとんどありません。そうでない場合-i(非推奨であり、-I {}代わりに移植性を使用する)、xargs標準または共通ツールで生成された入力形式は必要ありません。を使用すると-Iいくつxargsかの用途がありますが、パイプを使用する方が簡単ですfindfind -exec

拡張にはシェルが必要で{}/*、そのシェルは{}作業する実際のパスに置き換える必要があります。簡単な解決策は、シェルで1行ずつ実行することです。ドットファイルが省略されるため、3 つのパターンすべてがディレクトリ内のすべてのファイルをキャプチャするために使用されます。一部のパターンがどのファイルとも一致しない場合でも、既存のファイルを参照しない引数は無視される*ため重要ではありません。rm -f

… |
while read -r line; do
  sudo rm -rf -- "$line"/* "$line"/.[!.]* "$line"/..?*
done

シェルがワイルドカードを実行するには、ある時点でファイルを1つずつ処理する必要があるため、Xargsはここでは役に立ちません。ただし、一般的な手法が役に立つ可能性があるため、xargsからシェルにファイル名を返す方法があります。はシェルの引数_です(部分的には後続の引数$0に戻る必要はなく、で始まってもすべてが機能するようにするために存在します。そうしないとシェルのオプションとして扱われます)。これには2つのアプローチがあります。つまり、シェルに引数を繰り返すか、xargsに各シェル呼び出しに単一の引数を渡すように指示することです。$0$1-

… | xargs -I {} sudo sh -c 'for x; do rm -rf -- "$x"/* "$x"/.[!.]* "$x"/..?*; done' _ {}
… | xargs -I {} -n 1 sudo sh -c 'rm -rf -- "$1"/* "$1"/.[!.]* "$1"/..?*' _ {}

私はこれがls -d a*おもちゃの例であり、1行に1つのファイル名を生成するより複雑なコマンドがあるとします。にls -d a*なります。いいえlsほとんどの実装では、印刷できない文字を透明に出力しないために機能します。検索命令の場合-execと同じようにしてください。

find a* -exec sh -c 'rm -rf -- "$1"/* "$1"/.[!.]* "$1"/..?*' _ {} \; -prune

答え4

別のオプションは、xargsを呼び出す代わりにシェルループを使用することです。

例えば

ls -d a* | while read dir; do sudo rm -rf "$dir"/*; done;

主に例を挙げるために、パイプの中央にシェル構成を配置することで、これら2つの技術を組み合わせることもできます。

ls -d a* | while read dir; do ls -d "$dir"/*; done | xargs -d \\n rm -rf

xargsのオプションは、-d単に引数間の区切り文字が改行文字であることを指定することで、スペースを含むファイル名に関連する潜在的な致命的な問題を回避します(例deadly / file:)

関連情報