
いくつかのファイルを tar する必要があります。そのうちの 1 つはドットファイルです。
FILE1=/tmp/foo/.env
FILE2=/tmp/foo/docker-compose.yml
FILES="${FILE1#/} ${FILE2#/}"
tar -C / -cf /tmp/foo/files.tar "$FILES"
変数の置換によりtar: Removing leading '/' from member names
警告が回避され、解凍が簡単になります。
しかし、次のエラーが発生します:
tar: tmp/foo/.env tmp/foo/docker-compose.yml: stat できません: そのようなファイルまたはディレクトリはありません
パスをハードコーディングすると機能します: tar -C / -cf /tmp/foo/files.tar tmp/foo/.env tmp/foo/docker-compose.yml
。
問題はドットファイルの処理にあるのでしょうか、それともエスケープ処理に関係するものなのでしょうか?
答え1
シェルが展開されると"$FILES"
、スペースは構文上の値を失います。そのため、コマンドは単一のパスとしてtar
受け取られます。tmp/foo/.env tmp/foo/docker-compose.yml
同じように
file='a b'
touch "$file"
a b
2 つのファイルa
とではなく、ファイル が作成されますb
。
したがって、コメントで示唆されているように、ファイルごとに異なる変数を使用する必要がありますtar -C / -cf /tmp/foo/files.tar "${FILE1#/}" "${FILE2#/}"
。
直接実行が機能するのは、tar -C / -cf /tmp/foo/files.tar tmp/foo/.env tmp/foo/docker-compose.yml
スペースが構文上の価値を持ち、引数を別の引数から分離しているためです。「人間の目」では、"$FILES"
toの展開後に同じスペースが生成されますtmp/foo/.env tmp/foo/docker-compose.yml
が、この場合、引用符があるためスペースに特別な意味はなく、値全体が単一のパスとして扱われます。