私の 'rm'コマンドはMac端末では正しく実行されますが、シェルスクリプトでは実行されないのはなぜですか?

私の 'rm'コマンドはMac端末では正しく実行されますが、シェルスクリプトでは実行されないのはなぜですか?

名前にスペースを含むディレクトリがあります。この特定のディレクトリの内容を削除する必要があります。\内容を削除する前に、ディレクトリ名のスペースをエスケープします。このrmコマンドは端末では正常に機能しますが、シェルスクリプトで使用すると機能しません。わかりました。そのファイルやディレクトリはありません。間違い。

たとえば、次のディレクトリ構造があり、 Users/Neeraj/Documents/temp dir/dir with spaces/a.txt "dir with space" ディレクトリ内のすべてのエントリを削除する必要があります。私のシェルスクリプトのコードは次のとおりです。

#!/bin/sh
TEMP_DIR="$HOME/Documents/temp dir/dir with spaces"
TEMP_DIR=$(echo $TEMP_DIR | sed 's/ /\\ /g')
COMMAND="rm -r $TEMP_DIR/*"
echo "Command: $COMMAND"
rm -r "$TEMP_DIR"/*

このスクリプトを実行すると、次の結果が表示されます。そのファイルやディレクトリはありません。エラーが発生しましたが、コピーして端末で同じコマンドを実行すると正常に動作します。

出力:

Command: rm -r /Users/Neeraj/Documents/temp\ dir/dir\ with\ spaces/*
rm: /Users/Neeraj/Documents/temp\ dir/dir\ with\ spaces/*: No such file or directory

これを行う正しい方法は何ですか?

ノート:私はmacOSを使用しています

答え1

@Olorinsの回答はこの質問に対する正解ですが、より多くの情報を追加したいと思います。なぜこれはうまくいきません:


次のいずれかの方法を使用できます。

rm "dir with spaces"
rm dir\ with\ spaces
dir="dir with spaces"; rm "$dir"

しかし、これらはうまくいきません:

dir="dir\ with\ spaces";
rm "$dir" # the backslash will be taken literally inside quotes 
rm $dir # this should work, shouldn't it? Please read below.

後者のオプションは最初は私にとって直感的ではありませんでした。しかし、bashは変数の内容を拡張していくつかの参照を追加します。実行前

set -x以下を使用して、実際に実行されている内容を確認できます。

( var="a\ b"; set -x; echo $var; )
+ echo 'a\' b
a\ b

出力は問題ないようですが、スペースは\一重引用符で囲まれているため、まだエスケープされません。

答え2

2つの引用符を使用しています。そしてバックスラッシュがエスケープされます。参照を使うだけでも大丈夫です。

これで十分です。

TEMP_DIR="$HOME/Documents/temp dir/dir with spaces"
COMMAND="rm -r $TEMP_DIR/*"
echo "Command: $COMMAND"
rm -r "$TEMP_DIR"/*

この場合、ディレクトリ名が分割されるのを防ぐために、バックスラッシュと引用符の両方をシェルで処理する必要があります。両方を使用すると、シェルは両方のスペースを保持します。そして引用符の中にバックスラッシュがあるのでrm実際に.../temp\ dir/dir\ with\ spaces/....../temp dir/dir with spaces/...

印刷されたコマンドをコピーすると、シェルは余分な引用符なしでバックスラッシュを確認し、バックスラッシュで保護されたスペースを保持し、バックスラッシュを削除して引数に入りrmます。.../temp dir/dir with spaces/...

関連情報