出力を複数のファイルにリダイレクトしようとしたときに「tee:オープンすぎるファイル」を修正する方法

出力を複数のファイルにリダイレクトしようとしたときに「tee:オープンすぎるファイル」を修正する方法

jsonURLに保存されているファイルからURLをダウンロードする必要がありますcsv。これは手動で実行できないため、Pythonを使用してURLを1つずつ読み、curlダウンロードに渡す短いbashスクリプトを作成しました。また、teeスクリプトは、その助けを借りてダウンロードしたデータをファイルに保存し、標準コードを使用して各ファイルの名前を指定します。コードは同じフォルダに保存され、csvファイルは「Data」という別のフォルダに保存されます。

output_dir=Data
python pass_urls_to_std_out.py | xargs curl -k | tee $output_dir/$(python pass_cd_to_std_out.py) > /dev/null

pass_urls_to_std_out.pyURLを読み込み、1つずつ標準出力に渡す短いPythonスクリプトです。

pass_cd_to_std_out.pyコードを1つずつ読み込む同様のスクリプトです。

> /dev/nulltee画面にすべての出力が印刷されるのを防ぐために使用されます。curl

残念ながら、このスクリプトは小さなファイルセットでうまく機能しますが、ダウンロードするファイルの数が増えると、次のエラーメッセージが表示されます。

tee: 4208005.json: Too many open files
tee: 4110607.json: Too many open files
tee: 4304903.json: Too many open files
tee: 4217303.json: Too many open files
tee: 4212809.json: Too many open files
tee: 4214003.json: Too many open files
tee: 4208302.json: Too many open files
tee: 4203501.json: Too many open files
....

一度にファイルをすべて開かずに、出力を一度に1つのファイル(または一度に10、20ファイル)に順次リダイレクトする方法はありますか?

[編集]カミール・マコロフスキー私が書いて正確に指摘したように、pass_cd_to_std_out.py出力は1つずつ引数として渡されるのではなく、拡張され、一度teeに複数の引数に渡されます。

スクリプトをforループに書き直しました。

#!/bin/bash

output_dir=Data

for url in $(eval python pass_urls_to_std_out.py); do
        curl -k $url > $output_dir/$(python pass_cd_to_std_out.py)
done

残念ながら、これは$output_dir一度だけ評価されるので、出力は次のようになります。

Data/1200401.json
4205407.json
4106902.json
2304400.json
3304557.json
3205309.json
1600303.json
1400100.json

答え1

すべてをすぐにパイプするのではなく、各ステップをファイルに保存すると何らかの方法で動作することがわかりました。

  1. ディレクトリがDataあることを確認し、そうでない場合はディレクトリを作成しますData
    download_dir=Data
    
    if [ ! -d $download_dir ]; then
      mkdir $download_dir
    fi
    
  2. すべてのURLを含むファイルを作成します。
    python pass_urls_to_std_out.py >> urls.txt
    
  3. すべてのファイル名を含むファイルを作成します。
    python pass_cd_to_std_out.py >> file_names.txt
    
  4. 各ファイルを1行ずつ読み、URLからデータを再帰的にダウンロードし、ファイル名に保存します。
    paste urls.txt file_names.txt | while IFS= read -r url file_name; 
      do curl -k --output-dir=Data $url > $file_name; 
    done
    

そのオプションを追加しました--output-dir。ありがとうコサロナンダ 提案しかも。

関連情報