출력을 여러 파일로 리디렉션하려고 할 때 "tee: 너무 많은 열린 파일"을 수정하는 방법

출력을 여러 파일로 리디렉션하려고 할 때 "tee: 너무 많은 열린 파일"을 수정하는 방법

jsonURL 에 저장된 파일에서 URL을 다운로드 해야 합니다 csv. 이 작업을 수동으로 수행할 수 없기 때문에 Python을 사용하여 URL을 하나씩 읽고 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을 읽고 하나씩 표준 출력으로 전달하는 짧은 Python 스크립트입니다.

pass_cd_to_std_out.py코드를 하나씩 읽는 유사한 스크립트입니다.

> /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
....

한 번에 파일을 모두 열지 않고 출력을 한 번에 하나의 파일(또는 한 번에 10, 20개 파일)로 순차적으로 리디렉션하는 방법이 있습니까?

[편집]카밀 마코로프스키내가 쓰고 정확하게 지적했듯이, pass_cd_to_std_out.py출력은 하나씩 인수로 전달되는 것이 아니라 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. 각 파일을 한 줄씩 읽고 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. 감사합니다코살로난다 제안게다가.

관련 정보