以下を使用して、フォルダ内の.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
コマンドなので、最終的にはシステムコールを使用して別のプロセスで実行する必要があり、最終的に引数と環境変数の累積サイズの制限を超えます。bash
execve()
shellによって生成されたリストを印刷する必要がある場合は、ほとんどのシェルに組み込まれたリストを*.fits
使用できますprintf
(したがって呼び出されず、execve()
制限があります)。
printf '%s\n' *.fits > output_all.txt
しかし、これは次の質問を残します。
一致するファイルがない場合は、シェル*.fits
にそのまま残り、最終的に印刷されます。bash
*.fits
printf
*.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をnullglob
olumnに印刷します。ここで重要なのは、引数が渡されなければ何も印刷されないことです。print -rC1
r
1
C
を使用すると、zsh
glob修飾子(例:.
*.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ではファイル::検索ライブラリモジュールはfind
canなどの再帰検索を実行できますが、検索されたファイル名をフィルタリング、並べ替え、および操作し、そのファイルを処理できるPerlのすべての機能を使用できます。 File::Find
Perlに含まれるコアライブラリです。特定のディレクトリ内のファイルのみを検索する必要がある場合は、Perlのglob()
機能で十分です。
stilts
AFAICT 公開したリンクを見ると、竹馬の引数がin=@filename
NUL で区切られた入力を処理できないように見えます。したがって、ファイル名に改行を含む.fitsファイルがある場合は、そのファイルの名前を変更する必要があります。
もしstilts
できるNULで区切られたファイル名のリストを処理するには、のオプションを使用するか、find
Perlスクリプトでに変更して-print0
NULで区切られたリストを生成できます。これは何の関係もないかもしれませんが、NULを区切り文字として扱うことができる他のプログラムで同じ問題があるかどうかを知っておくと便利です(多くのプログラムに、および/またはオプションがあります)。\n
\0
stilts
-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