web-dev-qa-db-ja.com

スペースを含むファイルの名前を変更するbashエラー-mvターゲットはディレクトリではありません

スペースが含まれている一連のファイルの名前を変更して、スペースを削除しようとしています。私は正しいbashコマンドを見つけたと思った:

for f in *.txt; do mv \"$f\" ${f/ /}; done

ただし、これにより、各ファイルに対して「mv:ターゲットはディレクトリではありません」というエラーが発生します。コマンドで「mv」を「echo mv」に置き換えると、ファイルごとに適切なmvコマンドが出力され、それらのmvコマンドのいずれかを個別に入力すると機能します。たとえば、「a .txt」と「b .txt」の2つのファイルがあり、上記のコマンドを実行すると、次のようになります。

mv: target 'a.txt' is not a directory
mv: target 'b.txt' is not a directory

コマンドを入力すると:

for f in *.txt; do echo mv \"$f\" ${f/ /}; done

私は得ます:

mv "a .txt" a.txt
mv "b .txt" b.txt

「名前の変更」を使用してこれを行う別の方法を見つけましたが、これが機能しない理由を知りたいのですが。

16
Jim Hines

試してください:

for f in *.txt; do mv "$f" "${f// /}"; done

3つのポイント:

  1. シェル変数を囲む引用符はエスケープしないでください。

  2. 一般に、シェル変数へのすべての参照を二重引用符で囲むことをお勧めします。

  3. ${f/ /}は、最初に出現するスペースのみを削除します。すべてのスペースを削除するには、${f// /}を使用します。

何が悪かったのか

$ touch {a,b}" .txt"
$ ls *.txt
a .txt  b .txt
$ for f in *.txt; do mv \"$f\" ${f/ /}; done
mv: target `a.txt' is not a directory
mv: target `b.txt' is not a directory

\"$f\"は、二重引用符で囲まれたように動作しません。これは、"a.txt"などの2つの引数に展開されます。二重引用符は、aが通常の文字と同様に、通常の文字として扱われます。 mvには3つの引数("aおよび.txt"およびa.txt)があるため、mvは最初の2つの引数を3番目と3番目はディレクトリである必要があります。 3番目はディレクトリではないため、エラーメッセージが表示されます。

28
John1024

これはグーグルでこのエラーをグーグルするときに最初に出てきたものなので、少し追加すると思いました。

このエラーは、引数が3つ以上あり、最後の結果がディレクトリでない場合に発生します。

これは機能します:

mv file1.txt output.txt

これはしません:

mv file1.txt file2.txt

私の場合、私はやっていました:mv prefix_* output_file_nameダウンロードしたファイルに一貫した名前が付いているが、別のファイルがディレクトリに表示されているため、「mv target is not a directory」エラーが発生する

4
sdfgeoff