2개의 매개변수 입력 파일과 출력 파일이 필요한 Python 프로그램이 있습니다. 입력 파일을 읽고 출력 파일을 일부 수정하여 파일 복사본을 만듭니다.
매개변수 세트가 포함된 텍스트 파일을 만들었습니다. 여러 줄에 여러 매개변수 세트가 있습니다. 하지만 프로그램을 1회 실행하려면 한 줄씩 읽어야 합니다. 따라서 각 줄에는 입력 파일과 출력 파일이라는 2개의 매개변수(공백으로 구분)가 전달됩니다.
매개변수가 있는 파일의 예(이를 호출합니다.line.txt당 여러 매개변수가 있는 파일):
input-file-1-path/input-file-1-name.sql output-file-1-path/output-file-1-name.sql
input-file-2-path/input-file-2-name.sql output-file-2-path/output-file-2-name.sql
input-file-3-path/input-file-3-name.sql output-file-3-path/output-file-3-name.sql
input-file-4-path/input-file-4-name.sql output-file-4-path/output-file-4-name.sql
나는 이것을 시도했습니다 :
for arg in $(< /Users/Repository/File-With-Multiple-Arguments-Per-Line.txt);
do python /Users/Git-Repos/MyProgram.py "$arg" "$arg" ;
done.
사용법은 이렇습니다.python MyProgram.py input-file.txt output-file.txt
나는해야 할 일을합니다. 어떤 이유로든 각 인수를 3번 처리하지만(따라서 입력 파일인 첫 번째 인수도 출력 파일로 간주됩니다. 두 번째 인수와 동일합니다). 그래서 수정해서는 안 되는 입력 파일을 수정하게 되었습니다. 입력 및 출력 파일이 2개의 별도 git 저장소이기 때문에 이것을 알고 있습니다.
또한 하나만 사용했지만 "$arg"
내 프로그램이 필요한 두 번째 인수(출력 파일)를 받지 못했다는 사실을 발견했습니다. 내가 보는 것은 내 출력 파일이 아니지만 output: <stdout>
이를 사용하면 "$arg" "$arg"
내 프로그램이 잘못 해석됩니다. 이는 동일한 작업을 세 번 수행하는 것과 같습니다. 처음에는 예상 작업을 완료했고, 두 번째에는 출력 파일을 출력 및 입력으로 사용했습니다.
아래 해결 방법도 시도했지만 내 프로그램에서는 아무 작업도 수행되지 않습니다. 비록 그것이 해야 할 일을 수행하는 것처럼 내 터미널에 출력을 표시하지만. 오류가 발생하지 않았습니다.
while read x y; do
python /Users/Git-Repos/MyProgram.py "$x" "$y"
done < /Users/Repository/File-With-Multiple-Arguments-Per-Line.txt
답변1
파일의 각 줄에서 명령을 실행하고 해당 줄에서 공백으로 구분된 단어를 인수로 명령에 전달합니다 xargs -L1
.
따라서 이것은 다음과 같습니다.
xargs -L1 <File-With-Multiple-Arguments-Per-Line.txt python MyProgram.py
특정 형태의 인용이 이해되는 것처럼 xargs
공백이나 개행 문자를 포함하여 임의의 파일 경로와 함께 사용할 수 있습니다. 그러나 인용 구문은 sh
최신² 구문과 다릅니다. 둘 '...'
다 "..."
큰 따옴표이며 개행 문자를 포함할 수 없습니다. 예를 들어 다음과 같이 할 수 있습니다.
tamed-input-file tamed-output-file
"Input: it's "'such a "cool" path' 'Output: Not as cool'\
'as one with'\
'newline characters'
$ xargs -L1 <a printf '1:<%s> 2:<%s>\n'
1:<tamed-input-file> 2:<tamed-output-file>
1:<Input: it's such a "cool" path> 2:<Output: Not as cool
as one with
newline characters>
xargs
구현 에 따라 python
s stdin은 읽기 전용으로 열리 거나 와 (따라서 ) /dev/null
공유 되므로 stdin에서 읽지 않는 것이 중요합니다 . GNU 구현을 통해 다음을 사용할 수 있습니다.xargs
File-With-Multiple-Arguments-Per-Line.txt
python
xargs
xargs -L1 -a File-With-Multiple-Arguments-Per-Line.txt python MyProgram.py
그것을 고치십시오.
또한 대부분의 구현에서 xargs
명령 File-With-Multiple-Arguments-Per-Line.txt
은 비어 있는 경우 인수 없이 한 번 실행됩니다. 일부 xargs
구현에서는 이 옵션을 통해 이를 피할 수 있습니다 -r
.
당신에 대해:
for arg in $(< /Users/Repository/File-With-Multiple-Arguments-Per-Line.txt); do python /Users/Git-Repos/MyProgram.py "$arg" "$arg" ; done
먼저 IFS 분할 외에도 zsh
인용되지 않은 부분도 와일드카드의 영향을 받으므로 와일드카드가 포함된 파일 이름과 관련된 문제를 미리 피해야 합니다.$(<...)
set -o noglob
그런 다음 루프를 통과할 때마다 다음을 얻습니다.하나IFS로 구분되고( $IFS
기본적으로 공백, 탭 및 줄 바꿈 포함(zsh에서는 NUL)) 동일한 단어를 두 번 전달합니다 python
. 한 번에 두 단어를 얻으려면 다음을 수행해야 합니다 zsh
.
for file1 file2 in $(<File-With-Multiple-Arguments-Per-Line.txt); do
python MyProgram.py $file1 $file2
done
또는 bash에서:
set -o noglob
set -- $(<File-With-Multiple-Arguments-Per-Line.txt)
while (( $# > 0 )); do
python MyProgram.py $1 $2
shift "$(( $# < 2 ? $# : 2 ))"
done
이는 파일 경로에 공백, 탭 또는 줄바꿈이 포함될 수 없음을 의미합니다.
비슷한 작업을 수행 xargs -L1
하고 $IFS
각 줄에 모두 분리된 단어를 전달하려면 다음을 수행합니다 zsh
.
while IFS= read -ru3 line; do
python MyProgram.py $=line 3<&- # $=line for explicit IFS-splitting
done 3< File-With-Multiple-Arguments-Per-Line.txt
또는:
while read -ru3 -A files; do
python MyProgram.py $files 3<&-
done 3< File-With-Multiple-Arguments-Per-Line.txt
( 대체할 필요가 없는 한 ksh93
zsh에서도 작동 하지만 (zsh에서도 작동) bash에서는 작동 하지 않습니다 .)bash
"${files[@]}"
$files
-a
-A
POSIX적으로:
set -o noglob
while IFS= read -r <&3 line; do
python MyProgram.py $line 3<&- # implicit split+glob with glob disabled above
done 3< File-With-Multiple-Arguments-Per-Line.txt
여전히 임의의 파일 경로는 허용되지 않습니다. xargs -L1
dos 와 같은 특정 형태의 인용을 이해하는 단어로 줄을 나누려면 다음을 사용하십시오 zsh
.
while IFS= read -ru3 line; do
python MyProgram.py "${(Q@)${(z)line}}" 3<&- # $=line for explicit IFS-splitting
done 3< File-With-Multiple-Arguments-Per-Line.txt
여기서 z
매개변수 확장 플래그는 언어에서와 동일한 토큰화를 수행하여 인용의 한 레이어를 제거하고 zsh
인용 부호 안에 빈 매개변수를 남겨둡니다( 완료된 대로).Q
@
"$@"
그런 다음 다음을 사용할 수 있습니다.
"Input: it's "'such a "cool" path' $'Output: Not as cool\nas one with\nnewline characters'
¹ 너무 길지 않고 일부 xargs
구현을 통해 사용자 로케일에서 유효한 텍스트로 디코딩될 수 있습니다.
² 이는 Mashey 쉘( xargs
1970년대 후반 PWB Unix에 도입된 PWB 쉘이라고도 함)에 더 가깝습니다.
답변2
python
각 줄에 입력 파일 이름과 출력 파일 이름이 있는 파일의 내용을 반복한 다음 두 파일 이름을 인수로 전달하는 스크립트를 호출하려는 것 같습니다 .
문제가 python
파일을 읽을 수 있는 스크립트나 권한 또는 파일의 존재와 관련이 없다고 가정하면 while
질문의 예제가 작동합니다.
그러나 여기에 다음을 사용하는 대안이 있습니다 while
(이것은 Python에 전달된 인수만 표시하지만 아직 실행하지는 않았습니다).
§ cat File-With-Multiple-Arguments-Per-Line.txt | xargs -n 2 echo python
python input-file-1-path/input-file-1-name.sql output-file-1-path/output-file-1-name.sql
python input-file-2-path/input-file-2-name.sql output-file-2-path/output-file-2-name.sql
python input-file-3-path/input-file-3-name.sql output-file-3-path/output-file-3-name.sql
python input-file-4-path/input-file-4-name.sql output-file-4-path/output-file-4-name.sql
아래와 같이 해당 출력을 파일로 파이프한 다음 나중에 실행할 수 있습니다. 이렇게 하면 매개변수를 올바르게 전달했는지 확인하는 데 도움이 됩니다.
§ cat File-With-Multiple-Arguments-Per-Line.txt | xargs -n 2 echo python > script.sh
§ chmod +x ./script.sh
§ ./script.sh
다음과 같이 실행을 위해 bash로 파이프하여 스크립트를 직접 호출할 수도 있습니다.
§ cat File-With-Multiple-Arguments-Per-Line.txt | xargs -n 2 echo python | bash -