rmを使用して名前にスペースを含む複数のファイルを削除することはできません。

rmを使用して名前にスペースを含む複数のファイルを削除することはできません。

私は私のドットファイルの配布スクリプトを書いています。このファイルはデフォルトのGitリポジトリに保存されており、git checkout何千ものGitチェックアウトエラーなしでスムーズに実行するために、そのリポジトリのファイルを自分のホームディレクトリに保存しています。すでに存在する項目(.bashrc例:)を削除する必要がありますが、実際には次のように検索します。

git --git-dir=$HOME/repos/dots --work-tree=$HOME ls-tree --full-tree --full-name --name-only -r HEAD | sed "s|^|/mnt/home/henriquehbr/|"

注:その理由は、/mntこれが私のchrootインストール用のマウントポイントであり、実際にはカスタムArch Linuxインストールイメージで実行されているためです。

しかし、実際にはこれらのファイルを削除することは成功しませんでした。問題は、名前にスペースが含まれているファイルにあります(Font\ Awesome\ Icons.otf例:)。

上記のコマンドを次のコマンドシーケンスに渡して、削除する各ファイルを参照してみました。

<get_dotfiles> | sed "s|^|\"/mnt/home/henriquehbr/|" | sed "s/$/\"/"

rm上記はうまくいきません。引用符は文字通りファイル名の一部であるかのように扱われるようです。

もう一つの試みは良いループを作ることですfor

dotfiles=$(git --git-dir=$HOME/repos/dots --work-tree=$HOME ls-tree --full-tree --full-name --name-only -r HEAD | sed "s|^|/mnt/home/henriquehbr/|")

for dotfile in $dotfiles; do
    echo "$dotfile" # Works properly, displays dotfile path
    rm "$dotfile" # Doesn't works, writes: '$'\n'' after the path and fails
done

答え1

ヌルバイトを区切り文字として使用します。

git ls-tree -z … | xargs -0 rm

ほとんどのシェルでは、ヌルバイトを変数に入れることができないため、$(git ls-tree -z …)便利な操作は行われません。

引用符を渡す引用文を使用しようとすると機能しませんrmrmほとんどのプログラムと同様に、ファイル名のみが必要です。"ファイル名に表示される他の文字と同様に、通常の文字です。引用符を挿入することはシェルで置換するのに役立ちません。引用符($fooまたは$(mycommand …))を持たない変数置換またはコマンド置換は単に空白に分割されます(各単語はワイルドカードパターンとして扱われます)、このステップでは引用符は関係ありません。ファイル名自体に「エキゾチック」な文字(バックスラッシュ、タブ、二重引用符など)が含まれていない場合は、引用符を挿入してに渡すことが機能しますが、xargsandを使用するよりもはるかに複雑です。-0git ls-tree -zxargs -0

ファイル名にgit ls-tree引用符で囲まれた文字(改行を含む)が含まれていないと仮定すると、次のように動作します(引用符を中断せずに)。

set -f # disable wildcard expansion (globbing)
IFS='
' # set only newline as the word separator
for dotfile in $(git ls-tree …); do … 

これは良い考えではありません。実行時に既存のファイルを強制的に削除しようとすると、git checkoutGitは実行時にファイルを削除しますgit checkout -f …。重要なコンテンツが含まれている場合は、既存のファイルをチェックインする方が安全です。

git checkout -b original-files
git --git-dir=… ls-tree -z | xargs -0 git add
git commit -m "Original files on $HOSTNAME"
git checkout origin/master

答え2

私は実際にこれらすべての複雑さを必要としないより簡単な解決策で終わりました。デプロイ中に、単純な「強制」gitチェックアウトが以前のドットファイルのすべてを置き換えました。

git checkout -f

小物種は種ではない。存在するReddit

関連情報