이것은 매우 사소하고 가까운 답변을 많이 찾았지만 여전히 이를 파악할 수 없습니다. 기본적으로 다음과 같은 매개변수를 사용하여 스크립트를 만들었습니다.
var1=$1
echo "outside the pipe, my variable is set: $var1"
ls *.* | xargs sh -c 'echo "$0" "$@"; echo "inside the pipe, my variable is empty: $var1"'
내 문제는 내 변수 중 하나와 함께 파일 이름 목록을 파이프해야 한다는 것입니다. 어떻게 해야 합니까? 파일 목록을 배열에 쓴 다음 매개 변수를 추가/앞에 추가하고 파이프에 전달하려고 시도했지만 나중에 청크로 처리할 때 문제가 발생합니다. 원래 스크립트는 다음과 같습니다(imagemagick).
ls *.png | xargs -n 100 sh -c 'convert "$0" "$@" -evaluate-sequence $var1 ../out2/"$0"'
어떤 도움이라도 대단히 감사하겠습니다!
답변1
아니요, 파일 이름 목록을 파이프할 필요가 없습니다.
var1=$1
find . -maxdepth 1 -type f -name '*.png' -exec sh -c '
var1=$1; first=$2; shift 2
convert "$first" "$@" -evaluate-sequence "$var1" ../out2/"$first"' sh "$var1" {} +
즉, 내부 서브쉘을 $var1
첫 번째 인수로 사용합니다(0번째 인수는 쉘의 이름이어야 합니다).
$var1
내부 쉘은 인수 목록을 제거하고 find
발견된 첫 번째 경로 이름에 대해 동일한 작업을 수행합니다(이유는 모르겠지만 적어도 코드가 수행한다고 생각하는 것과 동일하게 만듭니다). 그런 $@
다음 shift 2
.
100개 단위로 이 작업을 수행해야 하는 경우:
var1=$1
find . -maxdepth 1 -type f -name '*.png' -print0 |
xargs -0 -n 100 sh -c '
var1=$1; first=$2; shift 2
convert "$first" "$@" -evaluate-sequence "$var1" ../out2/"$first"' sh "$var1"
이것이 파이프 출력보다 안전한 이유는 ls
경로 이름이 개행으로 끝나는 목록이 아닌 널로 끝나는 목록으로 전달되기 때문입니다. 스크립트 sh
는 두 변형 모두 동일하며 $var1
명령줄 인수로 제공됩니다.
코드가 작동하지 않는 이유는 쉘이 상위 쉘에서 무슨 일이 일어나고 있는지 sh -c
알지 못하기 때문입니다.$var1
관련된:
답변2
실제로 이 작업을 수행하기 위해 다른 쉘을 실행할 필요는 없습니다. glob 표현식과 일치하는 모든 파일을 처리하려면 최종적으로 실행하려는 프로그램의 명령줄에서 glob을 사용하면 됩니다.
convert *.png -whatever /some/output/path
파일의 일부에만 액세스해야 하는 경우 해당 파일을 배열에 저장하고 슬라이스하거나 인덱싱합니다.
files=(*.png)
convert "${files[0]}" "${files[@]:1}" -evaluate-sequence "$var1" ../out2/"${files[0]}"
( "${files[0]}"
첫 번째 파일 이름이며 "${files[@]:1}"
다른 모든 파일로 확장됩니다)
그러면 한 번에 100개의 파일을 처리할 수 있습니다.
for (( i=0; i < "${#files[@]}" ; i+=100 )); do
convert "${files[@]:i:100}" -evaluate-sequence "$var1" ../out2/"${files[i]}"
done
즉, 내가 당신의 명령을 올바르게 해석했다면 말이죠 xargs
. 첫 번째 파일 이름을 0번째 인수 sh -c
(보통 쉘 이름) 로 전달하는 것 같습니다 .
그러나 귀하의 질문에 대답하려면 export
변수를 사용하여 내부 쉘에 표시되도록 하거나 큰따옴표로 묶어 쉘에 의해 확장되도록 할 수 있습니다. 예를 들어
var=foo
export var
echo bar | xargs sh -c 'echo "$var" "$1"' sh
또는
var=foo
echo bar | xargs sh -c "echo '$var' "'"$1"' sh
둘 다 출력됩니다 foo bar
. 환경을 전달하는 것이 구문이 더 깨끗하고(주변 $var
과 $1
후자에 있는 다양한 유형의 따옴표 참고) 변수 값의 따옴표가 두 번째 경우처럼 문제를 일으키지 않기 때문에 더 좋습니다.
답변3
이것은 sh -c
새로운 쉘이므로 자식 프로세스가 이를 소유하거나 인수로 전달 export
하도록 of를 수행해야 합니다.$var1
sh -c
예제의 또 다른 문제는 단일 틱 내에 변수가 있다는 것입니다.