パススラッシュ後のBash支柱の拡張

パススラッシュ後のBash支柱の拡張

中かっこ拡張を使用して、異なる名前のファイルを同じディレクトリにコピーしようとしています。私はbash 4.4.18を使用しています。

これが私がしたことです:

cp ~/some/dir/{my-file-to-rename.bin, new-name-of-file.bin}

ただし、次のエラーが発生します。

cp: cannot stat '/home/xyz/some/dir/{my-file-to-rename.bin,': No such file or directory

このような単純な中括弧拡張にも同じエラーが発生します。

cp {my-file-to-rename.bin, new-name-of-file.bin}

私は何が間違っていましたか?

答え1

これ支柱の拡張構文にはカンマは使用できますが、コンマの後のスペースは使用できません。多くのプログラミング言語では、カンマの後のスペースは一般的ですが、ここではそうではありません。 Bashでは、引用符で囲まれていない空白がある場合、中括弧の拡張は行われません。

スペースを削除してください。

cp ~/some/dir/{my-file-to-rename.bin,new-name-of-file.bin}

完全に不要ですが、末尾を中.binかっこの外に移動できます。

cp ~/some/dir/{my-file-to-rename,new-name-of-file}.bin

支柱の拡張効果をテストするには、echoまたはprintf '%s '、またはを使用できます。printfこれを行うには、目的の書式文字列を使用してください。 (個人的にechoBashにいるときにこれを使用する理由は次のとおりです。バッシュecho内蔵エスケープシーケンスはデフォルトでは拡張されていないため、実行された実際のコマンドを調べるのに理想的です。 )例えば:

ek@Io:~$ echo cp ~/some/dir/{my-file-to-rename,new-name-of-file}.bin
cp /home/ek/some/dir/my-file-to-rename.bin /home/ek/some/dir/new-name-of-file.bin

答え2

string{foo, bar}中括弧の拡張ではなく、単なるstring{foo,単語ですbar}。中かっこ拡張を使用するには、中かっこが同じ単語内になければなりません。必要でない場合は余分なスペースを削除するか、本当に必要な場合は引用符を付ける必要があります。

$ printf "%s\n" aa{bb, cc}
aa{bb,
cc}
$ printf "%s\n" aa{bb,cc}
aabb
aacc
$ printf "%s\n" aa{bb," cc"}
aabb
aa cc

答え3

Bashはこの空間を他の空間と同様に扱います。 IFS として内部フィールド区切り記号です。これは拡張ワード分割に使用され、read組み込みコマンドを使用して行を単語に分割します。

シェルはIFSの各文字を区切り文字として扱い、他の拡張結果をこれらの文字の単語に分割します。 IFSが設定されていない場合、またはその値がデフォルト値の場合、前の拡張結果の始まりと終わりにある、およびシーケンスは無視され、始まりまたは終わりにないIFS文字シーケンスは区切るために使用されます。言葉。 IFSにデフォルト以外の値がある場合、スペース文字がIFS値(IFSスペース)にある限り、単語の先頭と末尾のスペースとタブのシーケンスは無視されます。 IFS スペースではなく、IFS のすべての文字と隣接する IFS スペース文字が一緒にフィールドを区別します。空白文字の IFS シーケンスも区切り文字と見なされます。 IFS値が空の場合、単語分割は発生しません。
-バッシュ(1)

エスケープされていない区切り文字を挿入すると、コマンドと引数が次のようになることをbashに通知できます。

  1. 「cp」
  2. "~/some/dir/{名前を変更するファイル.bin"
  3. 「新しいファイル名.bin}」

引用符またはエスケープ文字 "\"がある場合は、次のようにします。

  1. 「cp」
  2. "~/some/dir/{名前を変更するファイル.bin,\新しいファイル名.bin}"

「new-name-of-file.bin」が新しいファイル名でない限り、これは望むものではありません。スペースを含みます。角かっこ拡張が最初に発生し、次にチルダ拡張が発生するため、bashは次のことを行います。

  1. 「cp」
  2. "/path/to/home/some/dir/my-file-to-rename.bin"
  3. "/path/to/home/some/dir/\ 新しいファイル名.bin"

スペースだけを削除すると、すべての問題が解決されます。

関連情報