-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はありません。この制限を回避するには、パラメータリストを分割するexecve()必要があります。 GNUのGNU固有のオプションがxargsここで使用されます。-tmv

を使用すると、組み込みアイテムをzsh読み込むことができます。mv

zmodload zsh/files
mv -- * ..

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

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

withを置き換え./*./*(D)隠しファイルを移動したり、oNglob修飾子を追加してファイル名の並べ替えをスキップしたり、Nglob修飾子(with 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()計算は単にバイト合計以上であり、実行方法はオペレーティングシステムとバージョンによって異なります。

答え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 {} +

これらのバリエーションのどれも名前の衝突に興味がありません。正しくバックアップされたデータでテストする必要があります。

関連情報