別の答えは xargs
を強制することです コマンドをバッチで処理します。たとえば delete
まで ファイル 128 kB
一度に cd
ディレクトリに移動し、これを実行します:
echo *.pdf | xargs -n 100 rm
tl;dr
これは、コマンド ライン引数のサイズに対するカーネルの制限です。 for
を使用 代わりにループしてください。
問題の原因
これは execve
に関連するシステムの問題です と ARG_MAX
絶え間ない。これに関するドキュメントはたくさんあります (man execve、debian の wiki、ARG_MAX の詳細を参照してください)。
基本的に、展開はコマンドを生成します ARG_MAX
を超える (そのパラメーターを含む) limit.On カーネル 2.6.23
、制限は 128 kB
に設定されました .この定数は増やされており、次のコマンドを実行してその値を取得できます:
getconf ARG_MAX
# 2097152 # on 3.5.0-40-generic
解決策:for
を使用する ループ
for
を使用 BashFAQ/095 で推奨されているようにループし、RAM/メモリ スペース以外に制限はありません:
期待どおりのものが削除されることを確認するための予行演習:
for f in *.pdf; do echo rm "$f"; done
そしてそれを実行してください:
for f in *.pdf; do rm "$f"; done
また、glob はシェル間で強力で一貫した動作をする (POSIX 仕様の一部) ため、これは移植可能なアプローチです。
注: いくつかのコメントで指摘されているように、これは確かに遅くなりますが、より複雑なシナリオに適応できるため、保守性が高くなります。例 1 つ以上のアクションを実行したい場合。
解決策:find
を使用する
あなたが主張するなら、あなたは find
を使うことができます ただし、実際には xargs を使用しないでください 「NUL で区切られていない入力を読み取ると危険です (破損、悪用可能など)」 :
find . -maxdepth 1 -name '*.pdf' -delete
-maxdepth 1 ... -delete
の使用 -exec rm {} +
の代わりに find
を許可 外部プロセスを使用せずに必要なシステム コール自体を単純に実行するため、より高速になります (@chepner コメントに感謝します)。
参考文献
- 「引数リストが長すぎます」というメッセージが表示されます。大きなリストをチャンクで処理するにはどうすればよいですか? @ウールエッジ
- execve(2) - Linux man ページ (ARG_MAX を検索);
- エラー:引数リストが長すぎます @ Debian の wiki;
- 引用符で囲まれた引数を渡すと、「/bin/sh:引数リストが長すぎます」と表示されるのはなぜですか? @スーパーユーザー
find
-delete
があります アクション:
find . -maxdepth 1 -name '*.pdf' -delete
これが発生する理由は、bash が実際に一致するすべてのファイルにアスタリスクを展開し、非常に長いコマンド ラインを生成するためです。
これを試してください:
find . -name "*.pdf" -print0 | xargs -0 rm
警告: これは再帰的な検索であり、サブディレクトリ内のファイルも検索 (および削除) します。 -f
にタック 確認を必要としないことが確実な場合にのみ、rm コマンドを実行してください。
コマンドを非再帰的にするには、次のようにします:
find . -maxdepth 1 -name "*.pdf" -print0 | xargs -0 rm
別のオプションは、find の -delete
を使用することです フラグ:
find . -name "*.pdf" -delete