ファイル名に基づいて配列を作成しようとしていますが、スペースに問題があります。これは非常に一般的なようです。しかし、私が知っている限り、引用符は正しく設定され、配列がどのように構成されているかを推測します。
to_dump="$(find . -maxdepth 1 -print0 )"
to_dump_array=($to_dump)
read -p " -> " final
case "$final" in
a) for drop in "${to_dump_array[@]}" ;
do cp "$drop" --recursive --force Destination_Folder && \
echo "dropped \"$drop\" ;
done ;;
b) echo "Won't drop anything" ;;
esac
クエリクエリで配列を作成するより良い方法があるべきだと思います。また、私はまたどこに間違っていますか?
答え1
-print0
$(...)
bash変数の文字列はnullで終わるため、置換に使用しないでください。
私はこの質問が尋ねるのと同じ答えで質問しました。https://stackoverflow.com/a/30469553/1091693
次の答えをあなたの質問に合わせて調整してください。
to_dump=()
while IFS= read -r -d ''; do
to_dump+=( "$REPLY" )
done < <(find . -maxdepth 1 -print0)
その後、名前付き配列が作成され、to_dump
このread
コマンドを使用して配列からNULLで区切られた要素を読み取りますfind
。ここでパイプの代わりに使用する理由は、< <(...)
配列が変更されるのを防ぐ暗黙的なサブシェルを避けるためです。
元のfind
コマンドに1つが必要な場合-mindepth 1
や、.
再帰的にコピーする(現在のディレクトリ)を選択することができることは注目に値します。
私は-maxdepth 1
findのための引数として使用したことがわかりました。おそらくこれはもっと役に立つでしょう:
shopt -s nullglob
to_dump=( * .[!.]* ..?* )
避けてくださいfind
。これはbash組み込みのみを使用し、フォークせず、ほとんど非常にきれいです。
最初の行shopt -s nullglob
は、このオプションを有効にするbash(-only)コマンドですnullglob
。オプションは以下に説明されていますman 1 bash
。
設定されている場合、bashは、どのファイルとも一致しないパターン(上記のパス名の拡張を参照)を、自分ではなく空の文字列に拡張することを許可します。
簡単に言えば、入力したファイルが*
ファイルと一致しない場合は削除されます*
。デフォルトの動作は*
、とにかくそのファイルを置くことです。
2行目は配列に3つの球を追加します。
*
: 次から始まらないすべてのファイル.
.[!.]*
.
:1つと1つの非文字で始まるすべてのファイル.
。これは一致.
やディレクトリを避けるためです..
。..?*
..
: 1 つ以上の文字で始まるすべてのファイルです。これを追加する理由は前のglobと同じであり、欠落している場合が含まれます。
Bashはglobを配列定義に拡張し、正しく拡張します。スペースや同様の分割はありません。
nullglobの使用に関する警告:nullglobをオンにすると、カールは引数を渡さなかったと文句を言い、curl google.com/search?q=test
現在のls /var/fasdfasafs*
ディレクトリリストを提供します。これがデフォルトでオンになっていない理由の1つです。
答え2
次のように配列を作成します。
read -d $'\0' -r -a to_dump <<< $(find . -maxdepth 1 -print0)
答え3
find . -maxdepth 1
...あなたが望むものは次のとおりです。
a=()
for f in ./..?* ./.[!.]* ./*
do [ -e "$f" ] && a+=$f
done
答え4
あなたのスクリプトがあなたが思うように動作するかどうかはわかりません。私はこれがnullで終わるfind出力をファイル名のbash配列に変換するとは思いません。
to_dump_array=($to_dump)
forループの出力を確認して結果を確認しましたか?
for drop in "${to_dump_array[@]}"
do
echo -e "$drop\n"
done
find -print0で配列を埋める方法に関するいくつかのアドバイスを含むスタックオーバーフローがあります。
https://stackoverflow.com/questions/1116992/capturing-output-of-find-print0-into-a-bash-array
for ループの変数に直接代入するよりも、配列項目に対して配列索引付けを使用する方が良い場合があります。これにより、適切な分割のためにシェルに頼る必要がなくなります。
for drop in $(seq 0 $((${#to_dump_array[@]} - 1)))
do
cp "${to_dump_array[$drop]}"
これはあまり人気がないかもしれませんが、ファイル名のスペース(および他の珍しい文字)を管理するためにbash配列と複数のエスケープを使用する必要がある場合、シェルは設計された目的を超える可能性があります。
Python、Perl、Rubyなどがより高速で信頼性が高く、コードベースを管理およびデバッグするのがより簡単であることがわかります。
私はシェルスクリプトに適したレベルを超えている場合を知らせるために使用するいくつかの「リスクシグナル」を持っています。
- すべてのファイル名の状況を処理するための複数レベルのエスケープまたはヌル終了。
- 複数階層のシェル関数が互いに呼び出します。
- 複雑なデータ構造つまり、文字列と数字を超えています。
- 「性能最適化」を行っています。
- 式の「ラインノイズ」。
はい、上記のすべての作業を確実に実行できます。しかし、そうする必要がありますか?本当に…Python、Perl、Rubyなど。 Pythonでは非常に簡単です。スペースやバイナリ文字を含むファイル名やエスケープについて心配する必要はありません。
import os
dirListing = os.listdir("somedirectory")
for eachEntry in dirlisting:
doSomething