ファイル名リストに対して機能するbash関数の作成

ファイル名リストに対して機能するbash関数の作成

bashでこの関数を定義してcpfromserver実行するとき

$ cpfromserver xxx yyy zzz

私が入力したのと同じ結果

$ scp [email protected]:"/some/location/xxx/xxx.txt /some/location/xxx/xxx.pdf /some/location/yyy/yyy.txt /some/location/yyy/yyy.pdf /some/location/zzz/zzz.txt /some/location/zzz/zzz.pdf" /somewhere/else/

これはさまざまなパラメータで機能します。

(つまり、関数パラメータで指定した各関数に対して、関数はディレクトリをローカルディレクトリにコピーし、すべてのfilename.txt操作filename.pdfを単一の接続で実行する必要があります。)/some/location/filename/remote.server/somewhere/else/filenamessh

現在、単一のパラメータに対して機能する関数を作成し、それを繰り返しますが、これはssh各パラメータに対して別々の接続を作成するため、望ましくありません。

私の問題は、関数パラメータを場所(など)で個別に操作する方法だけを知っていますが、リスト全体で作業する方法はわかりません$1$2

[私はこの関数を独自の便利なツールで書いたので、引用符や改行などのファイル名などの病理学的なケースを処理するよりも理解しやすいことを優先します。私は私が使用するファイル名がうまく動作することを知っています。 ]

答え1

次の方法を試してください。

cpfromserver () {
    files=''
    for x in "$@"
    do
        files="$files /some/location/$x/$x.txt /some/location/$x/$x.pdf"
    done
    scp [email protected]:"$files" /somewhere/else/
}

コメントの重要な警告: 「複雑なファイル名には、このソリューションが確実に機能しないことに注目する価値があります。ファイル名にスペース、改行、または引用符が含まれている場合、このアプローチは間違いなく失敗します。」

答え2

簡単な例は次のとおりです。

#!/bin/bash

files_to_copy=''
destination_directory=''

while (("$#")) ; do
  if [[ "$@" = "$1" ]] ; then
    # last argument
    destination_directory="$1"
  else
    # argument
    files_to_copy="$files_to_copy $1"
  fi
  shift
done

scp [email protected]:"$files_to_copy" $destination_directory;

実行すると、次のようになり./example.sh foo.pdf foo.txt foo.jpg backup/ます。

# this will be executed
scp [email protected]:" foo.pdf foo.txt foo.jpg" backup/

答え3

主なアイデアは、(ループを介して)作業するファイルのリストを含む文字列を準備し、その文字列をコマンドにパイプすることです。

sloc='/some/location'
unset flist
for i in "$@"
do
    flist[${#flist[*]}]="$sloc/$i/$i".pdf
    flist[${#flist[*]}]="$sloc/$i/$i".txt
done
scp [email protected]:"${flist[@]}" /somewhere/else/

関連情報