내 스크립트가 glob 또는 STDIN(공백 포함)으로 제공된 여러 파일 이름을 읽고 이를 사용하여 작업을 수행하기를 원합니다. 두 가지 방법을 별도로 읽을 수는 있지만 결합할 수는 없습니다.
이는 명령줄에서 glob을 읽습니다.
for filename in "$@"; do
process_file "$filename"
done
이는 STDIN에서 읽습니다.
IFS=$'\n' read -d '' -r -a filenames
for filename in "${filenames[@]}"; do
process_file "$filename"
done
for filename in...
내가 정말로 원하는 것은 이들 중 하나를 배열로 읽어서 전체 루프를 두 번 반복할 필요가 없도록 하는 것입니다 . 이것이 명백하다면 죄송합니다. 저는 BASH를 처음 사용합니다.
편집: 가장 좋은 방법은 주어진 매개변수에서 이를 읽고 그렇지 않은 경우 기다리는 것입니다 STDIN
. 어떻게 해야 합니까?
편집: 좋습니다. 문제는 제가 생각했던 것과 다릅니다. 문제는 process_file에도 사용자 입력이 필요하다는 것입니다. STDIN
EOF에서 읽기를 시작하고 저장한 다음 다시 입력을 요청하는 방법이 있습니까 ?
답변1
텍스트 처리 도구는 일반적으로 명령줄에 파일 이름을 지정하지 않으면 표준 입력에서 입력을 읽습니다. 변수를 테스트하여 명령줄 인수가 있는지 확인할 수 있습니다 $#
. process_file
표준 입력에 인수가 전달되지 않으면 표준 입력에서 읽는다고 가정합니다 .
if [ $# -eq 0 ]; then
process_file
else
for x; do
process_file "$x"
done
fi
또는 process_file
인수가 필요한 경우 이를 전달하여 /dev/stdin
표준 입력에서 읽어 보십시오.
if [ $# -eq 0 ]; then set /dev/stdin; fi
for x; do
process_file "$x"
done
명령줄 인수 없이 표준 입력에서 읽을 파일 이름 목록을 요청하고 있습니다. 물론 가능하지만 특이하기 때문에 추천하지 않습니다. 사용자는 대부분의 다른 도구와는 다른 규칙을 배워야 합니다. 그럼에도 불구하고 다음과 같은 방법이 있습니다.
if [ $# -eq 0 ]; then
set -f # turn off globbing
IFS='
' # set newlines to be the only field separator
set -- $(cat)
set +f; unset IFS
fi
for x; do
process_file "$x"
done
답변2
새로운 답변 2021-10-18
bash: 다음에서 목록을 생성합니다.토론 그리고/또는 표준 입력
다음 작은 스크립트를 고려해보세요.
#!/bin/bash
declare -a ARGS=("$@")
while read -rt .02 arg;do
ARGS+=($arg)
done
declare -p ARGS
전화해서 argsAndInput.sh
샘플 요청도 가능하고...
seq 1 10 | ./argsAndInput.sh foo bar baz
declare -a ARGS=([0]="foo" [1]="bar" [2]="baz" [3]="1" [4]="2" [5]="3" [6]="4" [
7]="5" [8]="6" [9]="7" [10]="8" [11]="9" [12]="10")
seq 1 10 | ./argsAndInput.sh
declare -a ARGS=([0]="1" [1]="2" [2]="3" [3]="4" [4]="5" [5]="6" [6]="7" [7]="8"
[8]="9" [9]="10")
./argsAndInput.sh foo bar baz
declare -a ARGS=([0]="foo" [1]="bar" [2]="baz")
./argsAndInput.sh
declare -a ARGS=()
필요에 따라 제한시간( read -t .02
)을 줄이거나 다음을 사용할 수 있습니다.
while read -t 0 &&
read -r arg;do
ARGS+=($arg)
done
입력이 준비되었다고 확신하는 경우앞으로배쉬가 실행되어야 합니다.
오래된 답변
당신은 xargs
그것을 사용할 수 있습니다전환하다 STDIN
(항목이 많아도 명령줄 버퍼보다 훨씬 큽니다)논쟁.
아니면 다음과 같은 것일 수도 있습니다.
if [ $# -gt 0 ] ;then
for filename in "$@" ; do
process_file "$filename"
done
else
IFS=$'\n' read -d '' -r -a filenames
for filename in "${filenames[@]}"; do
process_file "$filename"
done
fi
아니면 둘다:
IFS=$'\n' read -d '' -r -a filenames
for filename in "${filenames[@]}" "$@" ; do
process_file "$filename"
done
fi
아니면 이런거 추가해서옵션, -l
대표하는 것처럼행 매개변수만, 다음에서 읽지(대기) 않도록 하세요 STDIN
.
case "$1" in
-l )
shift
for filename in "$@" ; do
process_file "$filename"
done
;;
* )
for filename in "${filenames[@]}" "$@" ; do
process_file "$filename"
done
;;
esac
(검증되지 않은!)
답변3
이것은 cygwin X11 gvim 및 Windows gvim에서 파일을 안전하게 열기 위해 작성한 스크립트입니다. 이는 쉘 래퍼로 설계되었으며 원하는 작업을 수행하는 부분입니다.
if [ ${#} -ne 0 ]; then #if we have filenames as CLArgs...
[[ ! -z ${DEBUG} ]] && echo "Got arguments [${#}]:'${@}'"
for OFILE in "${@}"; do
[[ -h ${OFILE} ]] && OFILE="$(readlink -f "${OFILE}")"
[[ ${WINVIM} == true ]] && OFILE=$(cygpath -wal "${OFILE}")
echo "\"${VIMRUN}\" --servername GVIM $RT \"${OFILE}\""
"${VIMRUN}" --servername GVIM $RT "${OFILE}" &
RT="--remote-tab"
done
else #otherwise read from stdin safely and handle spaces...
while read OFILE; do
[[ -h ${OFILE} ]] && OFILE="$(readlink -f "${OFILE}")"
[[ ${WINVIM} == true ]] && OFILE=$(cygpath -wal "${OFILE}")
echo "\"${VIMRUN}\" --servername GVIM $RT \"${OFILE}\""
"${VIMRUN}" --servername GVIM $RT "${OFILE}" &
RT="--remote-tab"
done
fi
답변4
이상 bash4.4
:
if [ "$#" -eq 0 ]; then
readarray -d '' args
set -- "${args[@]}"
fi
for arg do
something with "$arg"
done