多くのファイルでlsを使用すると、「bash:引数リストが長すぎます」というエラーが発生します。

多くのファイルでlsを使用すると、「bash:引数リストが長すぎます」というエラーが発生します。

以下を使用して、フォルダ内の.fitsファイルのすべての名前を入力しようとします。

ls *.fits > output_all.txt

フォルダ内の.fitsファイルの数が> 330,000で、エラーメッセージが表示されます。

bash: /usr/bin/ls: Argument list too long

この問題をどのように解決できますか?

または、ファイルを完全に生成する必要はありませんoutput_all.txt。私はただ話す必要があります。竹馬このコマンドを使用して、どの.fitsファイルを1つの大きな.fitsファイルにマージしますか?

stilts tcat in=@output_all.txt out=table_stilts.fits icmd='keepcols "FLUX LOGLAM"'

ファイルの代わりにディレクトリを入力として受け入れるようにSTILTSに指示する方法を知っていれば、私の問題は解決しますls。総窒素

答え1

で、シェルは、ls *.fitsで終わるか開始しないファイル名を見つけるためにすべての難しい作業を行います。.fits.

その後、そのリストをに渡しますls。これはそれを並べ替えます(やはり、シェルグロブがリストを渡す前に並べ替えたのでls)、後で表示します(実装と転送の有無によって列または行ごとに1つずつ)。端末へ)各ファイルが存在することを確認してください。

したがって、これは特に次の点を考慮するとわずかに非生産的です。

  • --オプションの区切り文字を忘れたため、ファイル名で始めると-問題が発生します。
  • オプションを忘れた-dため、ファイルがディレクトリタイプの場合は、ファイルls自体の代わりにその内容が一覧表示されます。
  • シェル(を含むほとんどのシェルでは)とは別のlsコマンドなので、最終的にはシステムコールを使用して別のプロセスで実行する必要があり、最終的に引数と環境変数の累積サイズの制限を超えます。bashexecve()

shellによって生成されたリストを印刷する必要がある場合は、ほとんどのシェルに組み込まれたリストを*.fits使用できますprintf(したがって呼び出されず、execve()制限があります)。

printf '%s\n' *.fits > output_all.txt

しかし、これは次の質問を残します。

一致するファイルがない場合は、シェル*.fitsにそのまま残り、最終的に印刷されます。bash*.fitsprintf*.fits<newline>

ls存在しない*.fitsファイルに関するエラーメッセージを表示して空白のままにしますoutput_all.txt

nullglobこれはオプション(bashからbashコピーzsh)を介して変更することができ、これにより*.fits拡張が空になります。しかし、別の問題に直面することになります。型を除いてパラメータが渡されない場合は、空のパラメータが渡されたかのprintfように型がまだ一度検索されますoutput_all.txt

この問題は次の方法で解決できます。

shopt -s nullglob
println() {
  [ "$#" -eq 0 ] || printf '%s\n' "$@"
}
println *.fits > output_all.txt

zsh代わりに、次に切り替えるとbash簡単になります。

print -rC1 -- *.fits(N) > output_all.txt

ここでglobをN有効にし、対応する引数awをnullglobolumnに印刷します。ここで重要なのは、引数が渡されなければ何も印刷されないことです。print -rC1r1 C

を使用すると、zshglob修飾子(例:.*.fits(N.)D*.fits(ND.)


最後に、ファイルの検索をいつでも遅らせることができますが、findリストを並べ替えて隠しファイルを除いてプレフィックスを避ける必要がある場合は、./この作業もすぐに退屈になり、GNU拡張が必要です。たとえば、次のようになりますprint -rC1 -- *.fits(N.)

LC_ALL=C find . -maxdepth 1 ! -name '.*' -type f -printf '%P\0' |
  sort -z | tr '\0' '\n' > output_all.txt

答え2

単一のコマンドラインで許可される文字数には制限があります。最新のLinuxシステムでは、約200万文字です。これは他のシステムによって異なる場合があります。

現在のディレクトリにある* .fitsファイルのファイル名が単一のコマンドラインに収まらないようです。この問題を解決する方法はいくつかあり、最も簡単な方法の1つはfind代替方法を使用することです。例えば

find . -maxdepth 1 -type f -name '*.fits' > output_all.txt

別のオプションは.egを使用することですperl

perl -e 'print map { "$_\n" if -f $_ } sort glob "*.fits"' > output_all.txt

または:

perl -E 'foreach $f (sort glob "*.fits") { say $f if -f $f }' > output_all.txt

でも:

perl -E 'foreach $f (sort grep { -f } glob "*.fits") { say $f }' > output_all.txt

(Perlにはこれを行う方法がたくさんあります。)

注:findバージョン〜する.現在のディレクトリに隠しファイル名(つまり、で始まるファイル名)がある場合は一覧表示します。パールバージョンに慣れる。どちらのバージョンも印刷のみ可能です。一般ファイル.fitsディレクトリ、シンボリックリンク、名前付きパイプ、ソケット、またはデバイスノードではなく終了します。出力はfindソートされず、ファイル名はディレクトリ内の順序で印刷されます。 Perlのバージョンはソートされます(昇順のアルファソート。ちょうどPerlの組み込みソート機能は、ファイルサイズやタイムスタンプを含むさまざまな基準に基づいてソートできるほど柔軟です)。

ところで、Perlではファイル::検索ライブラリモジュールはfindcanなどの再帰検索を実行できますが、検索されたファイル名をフィルタリング、並べ替え、および操作し、そのファイルを処理できるPerlのすべての機能を使用できます。 File::FindPerlに含まれるコアライブラリです。特定のディレクトリ内のファイルのみを検索する必要がある場合は、Perlのglob()機能で十分です。


stiltsAFAICT 公開したリンクを見ると、竹馬の引数がin=@filenameNUL で区切られた入力を処理できないように見えます。したがって、ファイル名に改行を含む.fitsファイルがある場合は、そのファイルの名前を変更する必要があります。

もしstilts できるNULで区切られたファイル名のリストを処理するには、のオプションを使用するか、findPerlスクリプトでに変更して-print0NULで区切られたリストを生成できます。これは何の関係もないかもしれませんが、NULを区切り文字として扱うことができる他のプログラムで同じ問題があるかどうかを知っておくと便利です(多くのプログラムに、および/またはオプションがあります)。\n\0stilts-z-Z-0

find . -maxdepth 1 -type f -name '*.fits' -print0 > output_all.nul

または

perl -e 'print map { "$_\0" if -f "$_" } sort glob "*.fits"' > output_all.nul

関連情報