파일을 업로드하기 위한 간단한 대체 스크립트를 작성하려고 합니다.파일 전송제공하다. 웹사이트의 예에서는 단일 "세션"에서 여러 파일을 업로드하는 방법을 언급합니다.
$ curl -i -F filedata=@/tmp/hello.txt \
-F filedata=@/tmp/hello2.txt https://transfer.sh/
저는 원하는 수의 매개변수(파일)를 허용하고 이 방식으로 cURL에 전달할 수 있는 함수를 만들려고 합니다. 기능은 다음과 같습니다:
transfer() {
build() {
for file in $@
do
printf "-F filedata=@%q " $file
done
}
curl --progress-bar -i \
$(build $@) https://transfer.sh | grep https
}
파일 이름에 공백이 없으면 함수는 예상대로 작동합니다. 출력 결과 printf "-f filedata=@%q " "hello 1.txt"
는 -F filedata=@test\ 1.txt
특수 문자가 올바르게 이스케이프될 것으로 기대합니다. 그러나 공백이 포함된 파일 이름으로 함수를 호출하는 경우:
$ transfer hello\ 1.txt
cURL이 이스케이프를 해석할 수 없는 것 같고 오류를 보고합니다.
curl: (26) couldn't open file "test\"
또한 명령의 일부를 인용해 보았습니다 printf "-F filedata=@\"%s\" " "test 1.txt"
. -F filedata=@"test 1.txt"
이 경우 cURL은 동일한 오류를 반환합니다 curl: (26) couldn't open file ""test"
. 따옴표에는 전혀 신경 쓰지 않는 것 같습니다.
이 동작의 원인이 무엇인지 잘 모르겠습니다. 공백이 포함된 파일 이름도 처리하도록 이 함수를 어떻게 수정합니까?
편집/해결책
@meuh가 설명했듯이 이 문제는 배열을 사용하여 해결할 수 있습니다. 두 가지 모두에 적합한 솔루션은 다음과 bash
같습니다 zsh
.
transfer () {
if [[ "$#" -eq 0 ]]; then
echo "No arguments specified."
return 1
fi
local -a args
args=()
for file in "$@"
do
args+=("-F filedata=@$file")
done
curl --progress-bar -i "${args[@]}" https://transfer.sh | grep https
}
zsh
합계의 출력은 다음 bash
과 같습니다.
$ ls
test space.txt test'special.txt
$ transfer test\ space.txt test\'special.txt
######################################################################## 100.0%
https://transfer.sh/z5R7y/test-space.txt
https://transfer.sh/z5R7y/testspecial.txt
$ transfer *
######################################################################## 100.0%
https://transfer.sh/4GDQC/test-space.txt
https://transfer.sh/4GDQC/testspecial.txt
Linux 및 OS X에서는 xsel --clipboard
함수의 출력을 클립보드로 사용하거나 파이프하는 것이 좋습니다.xclip
pbcopy
@Jay가 제공하는 솔루션도 매우 잘 작동합니다.
transfer() {
printf -- "-F filedata=@%s\0" "$@" \
| xargs -0 sh -c \
'curl --progress-bar -i "$@" https://transfer.sh | grep -i https' zerop
}
답변1
다음의 표준적이고 안전한 솔루션을 사용해 보세요.
transfer() {
printf -- "-F filedata=@%s\0" "$@" | xargs -0 sh -c 'curl --progress-bar -i "$@" https://transfer.sh | grep -i https' zerop
}
"$@"
큰따옴표를 추가하면 쉘이 원래 옵션을 변경하지 않은 채로 유지됩니다. 바라보다2.5.2 특수 매개변수부분적으로Open Group 기본 사양 6호:
@
1부터 시작하는 위치 매개변수로 확장됩니다. 확장이 발생하면큰따옴표 안에및 필드 분할(참조필드 분할When 원어의 마지막 부분과 연결되어야 합니다. 위치 인수가 없으면 "@"을 큰따옴표로 묶은 경우에도 "@"을 확장하면 0개의 필드가 생성됩니다.
이 방법을 사용하는 printf
것이 옵션을 처리하는 표준 방법입니다. 이를 테스트하여 결과가 -F filedata=@
옵션 수만큼 문자열을 생성하는지 확인할 수 있습니다.
이름에 특수 문자가 포함된 2개의 파일로 테스트되었습니다.
$ ls -b
f\ rst s'cond
$ transfer() { printf -- "-F filedata=@%s\0" "$@" | xargs -0 sh -c 'curl --progress-bar -i "$@" https://transfer.sh | grep -i https' zerop ;}
$ transfer *
######################################################################## 100.0%
https://transfer.sh/fnzuh/f-rst
https://transfer.sh/fnzuh/scond
답변2
Bash 토큰화를 피하는 한 가지 방법은 배열을 사용하여 탈출하지 않고 각 인수를 전달하는 것입니다.
push(){ args[${#args[*]}]="$1"; }
build() {
args=()
for file
do push "-F"
push "filedata=@$file"
done
}
build "$@"
curl --progress-bar -i "${args[@]}" https://transfer.sh | grep https
이 build
함수는 배열을 만들고 args
배열 push
끝에 새 값을 추가합니다. 간단히 curl
배열을 사용하십시오.
첫 번째 부분은 단순화하거나 push
간단히 로 작성할 수 있으므로 args+=("$1")
이를 제거하고 build
다음으로 변경할 수 있습니다.
build() {
args=()
for file
do args+=("-F" "filedata=@$file")
done
}