ファイルをアップロードするための簡単な代替スクリプトを作成しようとしています。ファイル転送提供する。ウェブサイトの例では、単一の「セッション」から複数のファイルをアップロードする方法について説明します。
$ 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 原語の最後の部分に関連付ける必要があります。位置引数がない場合は、「@」を二重引用符で囲んでも「@」を展開するとゼロ個のフィールドが生成されます。
この方法の使用は、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トークン化を回避する1つの方法は、配列を使用してエスケープせずに各引数を渡すことです。
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
}