次のファイル/ディレクトリを含むディレクトリがあるとします。
google
apple
mozilla foundation # a file with spaces
browsers
browsers
だからファイルをディレクトリに移動したいと思います。私が書いたスクリプトは次のとおりです。
for d in $(ls); do
if ! [ "$d" == "browsers" ]; then
mv "$d" "browsers"
fi
done
それから行きましたが、google
得ました。apple
browsers
mv: cannot stat 'mozilla': No such file or directory
mv: cannot stat 'foundation': No such file or directory
明らかに問題は変数の空白です。この問題を処理する正しい方法は何ですか?
もちろん、これを行うには、よりエレガントな1行のコマンドが必要であると確信していますが、空白のある変数をどのように使用するかを知りたいです。
答え1
するいいえ使用した:
for d in $(ls)
代わりにこれを使用してください:
for d in *
これを使用する際の2つの問題は、$(ls)
シェルが結果を$(ls)
次のように適用することです。噴射そしてパス名拡張。あなたが思う限り、そうです噴射これが mozilla foundation
原因とmozilla
なりますfoundation
。
を使用しない理由の詳細については、$(ls)
次を参照してください。「何してる$(ls *.txt)
?」
ディレクトリに隠されていないファイルがない場合を考慮する必要がある場合(この場合はループ内でfor i in $(ls)
1回のパスを実行するのではなく(*
除く)、ループ内でパスを実行しないため、より良く見える場合があります)、一致しないグローブに拡張しないようにシェルに指示したいと思います。$i
for i in *
zsh
zsh
:for i in *(N)
ksh93
:for i in ~(N)*
bash4.4+
:(f() { local -; shopt -s nullglob; for i in *; ...; done; }; f
このオプションをローカルで使用することを強調表示します(デフォルトオプションと同様の動作nullglob
については、このオプションも参照してください))。failglob
zsh
yash
:(それからリセットします。私が知っている限り、ローカルスコープset -o nullglob
オプションはありません)yash
- 他のシェルでは、常に
[ -e "$i" ] || [ -L "$i" ] || continue
ループに追加してファイルが存在することを確認できます。
答え2
ls
結果を解析しない、John1024の答えに加えてfind
。
LC_ALL=C find . ! -name . -prune ! -name '.*' -type f -exec mv -t /path/to/dest {} +
(これはGNUfind
オプションが使用され、globなど-t
の隠しファイルをスキップし、非正規ファイルを除外すると仮定します。リストはソートされません(または逆)。名前がこれらで始まるすべてのファイルは正しくスキップする必要があります。有効な文字には含まれませんが、これはエラーメッセージの言語に影響します。ls
*
ls
*
LC_ALL=C
.