-bash: /usr/bin/mv: 引数リストが長すぎます

-bash: /usr/bin/mv: 引数リストが長すぎます

このコマンドを使用するとmv * ..、エラーが発生します-bash: /usr/bin/mv: Argument list too long。これが発生する理由は、bash が実際にアスタリスクをすべての一致するファイルに展開し、非常に長いコマンド ラインを生成するためだと理解しています。このエラーを修正するにはどうすればよいですか?

答え1

制限は bash ではなく、execve()外部コマンドを実行するために使用されるシステム コールにあります。次のように実行できます。

printf '%s\0' * | xargs -r0 mv -t .. --

printfは に組み込まれているため、その時点ではbashはありません。そして、その制限を回避するために引数のリストを分割することが の仕事です。ここでは、GNU のGNU 固有のオプションを使用しています。execve()xargs-tmv

を使用するとzsh、組み込みをロードできますmv

zmodload zsh/files
mv -- * ..

または、zargsヘルパーを使用して分割を実行します。

autoload -Uz zargs # best in ~/.zshrc
zargs -r -- ./* -- mv -t ..

./*を に置き換え./*(D)て隠しファイルも移動したり、oNglob 修飾子を追加してファイル名のソートをスキップしたり、Nglob 修飾子 ( を使用zargs -r) を追加して一致するファイルがない場合にエラーを回避したりすることもできます。

zargs -r -- ./*(ND) -- mv -t ..

と同じ:

print -rNC1 ./*(ND) | xargs -r0 mv -t ..

ただし、 GNU への依存性はありませんxargs

Linux (Ubuntu で一般的に使用されるカーネル) では、リソース制限execve()を上げることでその制限を上げることもできますstacksize

bash-5.1$ /bin/true {1..200000}
bash: /bin/true: Argument list too long
bash-5.1$ ulimit -s unlimited
bash-5.1$ /bin/true {1..200000}
bash-5.1$ 

完全に無制限というわけではありません (少なくともカーネルの現在のバージョンではそうではありません)。

bash-5.1$ /bin/true {1..2000000}
bash: /bin/true: Argument list too long

制限は、 に渡される引数と環境変数の合計サイズにありますexecve()が、計算は単にバイトの合計ではなく、その方法は OS とそのバージョンによって異なります。

答え2

2 つ以上のステップで実行できます。

mv [a-k]* ..    # or some other pattern matching a subset of the files
mv -- * ..

あるいはループで、

for name in *; do
    mv -- "$name" ..
done

(ただし、これにはmvそれぞれの名前が個別に必要になります。)

または、次のfind方法でお手伝いします:

find . -mindepth 1 -maxdepth 1 -exec mv -t .. -- {} +

これにより、現在のディレクトリ内のすべての名前が検索され、GNU を使用して、 の呼び出しをできるだけmv少なくして、それらの名前が上のディレクトリに移動します。mv

GNU はなくてmvも、find非標準の述語-mindepth-maxdepth述語を認識している があれば、

find . -mindepth 1 -maxdepth 1 -exec sh -c 'mv -- "$@" ..' sh {} +

これらのバリエーションはいずれも名前の衝突を気にしません。適切にバックアップされたデータでテストする必要があります。

関連情報