인수를 foo.txt
지정 하는 파일이 있습니다.N
arg1
arg2
...
argN
내가 명령에 전달해야 my_command
파일의 줄을 명령의 인수로 어떻게 사용합니까?
인수를 foo.txt
지정 하는 파일이 있습니다.N
arg1
arg2
...
argN
내가 명령에 전달해야 my_command
파일의 줄을 명령의 인수로 어떻게 사용합니까?
답변:
쉘이 bash (다른 것들 중에서)라면 바로 가기는 $(cat afile)
입니다 $(< afile)
.
mycommand "$(< file.txt)"
'명령 대체'섹션의 bash 매뉴얼 페이지에 설명되어 있습니다.
또는 stdin에서 명령을 읽도록하십시오. mycommand < file.txt
<
연산자 를 사용하는 지름길이 아닙니다 . 이것은 쉘 자체가 cat
리디렉션 속성에 대해 바이너리를 실행하는 대신 리디렉션을 수행한다는 것을 의미합니다 .
"$(…)"
의 내용이 인수가 아닌 file.txt
의 표준 입력으로 전달 되기 때문 mycommand
입니다. "$(…)"
즉 , 명령을 실행하고 출력을 문자열로 제공합니다 . 여기서 "명령"은 파일 만 읽지 만 더 복잡 할 수 있습니다.
이미 언급했듯이 백틱 또는을 사용할 수 있습니다 $(cat filename)
.
언급되지 않았으며 주목해야 할 것은 쉘이 공백에 따라 해당 파일의 내용을 분리하고 명령에 찾은 각 "단어"를 인수로 제공한다는 점을 기억해야한다는 것입니다. 또한 공백, 이스케이프 시퀀스 등을 포함 할 수 있도록 명령 줄 인수를 따옴표로 묶을 수는 있지만 파일을 읽더라도 동일한 작업을 수행하지는 않습니다. 예를 들어 파일에 다음이 포함 된 경우
a "b c" d
당신이 얻을 인수는 다음과 같습니다
a
"b
c"
d
각 줄을 인수로 가져 오려면 while / read / do 구문을 사용하십시오.
while read i ; do command_name $i ; done < filename
read -r
백 슬래시 이스케이프 시퀀스를 확장하지 않으려면 읽어야합니다 . 특히 전달하는 인수가 파일 이름과 같이 문자 그대로의 개행 문자를 포함 할 수있는 경우 NUL은 개행 문자보다 사용하기에 더 안전합니다. 또한 IFS를 지우지 않고에서 앞뒤 공백을 암시 적으로 얻을 수 있습니다 i
.
command `< file`
stdin에서 명령에 파일 내용을 전달하지만 줄 바꿈을 제거하므로 각 줄을 개별적으로 반복 할 수 없습니다. 이를 위해 'for'루프를 사용하여 스크립트를 작성할 수 있습니다.
for line in `cat input_file`; do some_command "$line"; done
또는 (여러 줄 변형) :
for line in `cat input_file`
do
some_command "$line"
done
또는 ( $()
대신에 여러 줄 변형 ``
) :
for line in $(cat input_file)
do
some_command "$line"
done
< file
백틱을 넣으면 실제로 리디렉션을 command
전혀 수행하지 않습니다 .
command `< file`
작동하지 않습니다 . zsh는 다른 문제이지만이 질문의 핵심은 아닙니다.)
Hello World
한 줄에 두십시오 . 먼저 실행 된 some_command Hello
다음 some_command World
, 그렇지 않은 some_command "Hello World"
또는을 볼 수 some_command Hello World
있습니다.
당신은 백틱을 사용하여 그렇게합니다 :
echo World > file.txt
echo Hello `cat file.txt`
echo "Hello * Starry * World" > file.txt
*
fork()
다음의 표준 출력에 부착 된 FIFO와 서브 쉘 떨어져 보내고 호출 /bin/cat
한 후 FIFO를 통해 출력을 읽고, 그 서브 쉘의 자식으로; $(<file.txt)
서브 쉘이나 FIFO를 사용하지 않고 파일 내용을 bash로 직접 읽는 것과 비교합니다 .
가능한 모든 명령 줄 인수 (공백이있는 값, 줄 바꿈이있는 값, 리터럴 따옴표 문자가있는 값, 인쇄 할 수없는 값, glob 문자가있는 값 등)에 대해 강력한 방법 으로이 작업을 수행하려면 약간의 가치가 있습니다. 더 흥미로운.
인수 배열이 주어지면 파일에 쓰려면 다음을 수행하십시오.
printf '%s\0' "${arguments[@]}" >file
... 교체 "argument one"
, "argument two"
적절하게, 등.
해당 파일에서 읽고 해당 내용을 사용하려면 (bash, ksh93 또는 배열이있는 다른 최신 쉘) :
declare -a args=()
while IFS='' read -r -d '' item; do
args+=( "$item" )
done <file
run_your_command "${args[@]}"
해당 파일에서 읽고 내용을 사용하려면 (배열이없는 쉘에서) 로컬 명령 줄 인수 목록을 덮어 쓰므로 함수 내부에서 수행하는 것이 가장 좋습니다. 따라서 함수의 인수를 덮어 쓰지 않아야합니다. 전체 목록) :
set --
while IFS='' read -r -d '' item; do
set -- "$@" "$item"
done <file
run_your_command "$@"
그 주 -d
(다른 끝 (end-of-line) 구분 기호를 사용할 수 있도록)는 비 POSIX 확장하고, 배열이없는 쉘은 또한 그것을 지원하지 않을 수 있습니다. 이 경우 NUL로 구분 된 내용을 eval
안전한 형식 으로 변환하기 위해 쉘이 아닌 언어를 사용해야 할 수도 있습니다 .
quoted_list() {
## Works with either Python 2.x or 3.x
python -c '
import sys, pipes, shlex
quote = pipes.quote if hasattr(pipes, "quote") else shlex.quote
print(" ".join([quote(s) for s in sys.stdin.read().split("\0")][:-1]))
'
}
eval "set -- $(quoted_list <file)"
run_your_command "$@"
다음은 파일의 내용을 명령의 인수로 전달하는 방법입니다.
./foo --bar "$(cat ./bar.txt)"
$(<bar.txt)
bash와 같은 쉘을 적절한 확장으로 사용하는 경우) 와 실질적으로 덜 효율적이지만 실질적으로 덜 효율적 입니다. $(<foo)
특별한 경우입니다 :에서 사용되는 일반 명령 대체와 달리 $(cat ...)
서브 쉘을 포크하지 않아서 많은 오버 헤드를 피할 수 있습니다.
내 bash 쉘에서 다음은 매력처럼 작동했습니다.
cat input_file | xargs -I % sh -c 'command1 %; command2 %; command3 %;'
여기서 input_file은
arg1
arg2
arg3
분명,이 당신이 INPUT_FILE에서 각 라인, 내가 배운 좋은 작은 트릭으로 여러 명령을 실행할 수 있습니다 여기에 .
$(somecommand)
있으면 텍스트로 전달되지 않고 해당 명령이 실행됩니다. 마찬가지로, >/etc/passwd
리디렉션 및 덮어 쓰기 /etc/passwd
(적절한 권한으로 실행되는 경우) 등 으로 처리됩니다 .
xargs -d $'\n' sh -c 'for arg; do command1 "$arg"; command2 "arg"; command3 "arg"; done' _
또한 입력 파일에서 한 줄에 하나의 쉘을 시작하는 대신 가능한 한 많은 인수를 각 쉘에 전달하기 때문에 더 효율적입니다.
cat
@Wesley Rice의 답변 을 몇 번 편집 한 후 , 내 자신의 글을 쓰는 대신 자신의 답변을 계속 변경하기에 변경 사항이 너무 커지기 로 결정했습니다. 그래서 나는 내 자신을 작성하기로 결정했습니다!
파일의 각 줄을 읽고 다음과 같이 한 줄씩 실행하십시오.
#!/bin/bash
input="/path/to/txt/file"
while IFS= read -r line
do
echo "$line"
done < "$input"
이것은 저자 Vivek Gite에서 직접 온 것입니다 : https://www.cyberciti.biz/faq/unix-howto-read-line-by-line-from-file/ . 그는 신용을 얻는다!
구문 : Bash Unix & Linux 쉘에서 한 줄씩 파일 읽기 :
1. bash, ksh, zsh 및 다른 모든 쉘이 한 줄씩 파일을 읽는 구문은 다음과 같습니다
.while read -r line; do COMMAND; done < input.file
3.-r
옵션은 읽기 명령에 전달되었습니다. 백 슬래시 이스케이프가 해석되지 않도록합니다.
4.IFS=
선행 / 후행 공백이 잘리지 않도록 읽기 명령 전에 옵션을 추가하십시오
.while IFS= read -r line; do COMMAND_on $line; done < input.file
그리고 지금 내가 가지고있는이 닫힌 질문에 대답하기 위해 : 파일에서 파일 목록을 'git add'할 수 있습니까? -내 대답은 다음과 같습니다.
참고 FILES_STAGED
각 라인은 내가하고 싶은 파일에 대한 상대 경로 라인의 무리가 포함 된 파일의 절대 경로가 포함 된 변수 git add
에 있습니다. 이 코드 스 니펫은 이 프로젝트 의 "eRCaGuy_dotfiles / useful_scripts / sync_git_repo_to_build_machine.sh" 파일의 일부가 되어 한 PC (예 : 코드가있는 컴퓨터)에서 다른 PC (예 : 코드가있는 컴퓨터)에서 개발중인 파일을 쉽게 동기화 할 수 있습니다. 더 강력한 컴퓨터) : https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles .
while IFS= read -r line
do
echo " git add \"$line\""
git add "$line"
done < "$FILES_STAGED"
git add
: 파일에서 파일 목록을 'git add'할 수 있습니까?