作業ディレクトリにdjvuファイルが1つしかないとします。.bk
ファイル名の末尾に追加の内容を含むファイルにファイルをバックアップしたいと思います。cp *.djvu{,.bk}
djvuファイルをというファイルにコピーします*.djvu.bk
。*
バックアップファイル名に拡張子がないのはなぜですか?どうやって?
答え1
何が起こるかは、bashが最初に拡張され、次に*.djvu{,.bk}
glob*.djvu *.djvu.bk
が拡張されることです。これはあなたが観察しているものを説明します。あなたの場合は、*.djvu
既存のファイルと一致し、foo.djvu
そのファイルに拡張されますが、*.djvu.bk
どのファイルとも一致しないため、独自に拡張されます*.djvu.bk
。
拡張順序は bash 文書で指定されています。
The order of expansions is: brace expansion, tilde expansion, parame‐
ter, variable and arithmetic expansion and command substitution (done
in a left-to-right fashion), word splitting, and pathname expansion.
コピーコマンドを次のように書き直すことをお勧めします。
for f in *.djvu; do cp -- "$f" "$f".bk; done
または、明示的なforループの構文オーバーヘッドを回避するには、次の手順を実行します。
parallel -j1 cp -- {} {}.bk ::: *.djvu
(もう一度考えてみてください。それほど短いわけではありません。)
「拡張方法」というサブ質問に答えるには、サブコマンドを使用できます(例:およびのみを含むfoo.djvu
ディレクトリからbar.djvu
)。
$ echo $(echo *.djvu){,.bk}
bar.djvu foo.djvu bar.djvu foo.djvu.bk
ただし、これは上記のforループや並列呼び出しほど安全ではありません。スペースを含むファイル名では競合が発生します。
答え2
中括弧拡張は別の単語を生成しますが、ワイルドカード拡張はワイルドカードパターンがすでに別の単語にある場合は最後に発生するため、ワイルドカード拡張の前に中括弧拡張が発生します。 (とにかく反対方向に発生すると、cp *.djvu{,.bk}
名前がitで終わるファイルがないため、一致するものはなく、.djvu{,.bk}
中括弧拡張は2つの単語*.dvju
とを生成します*.djvu.bk
。)したがって、最初の単語はcp *.djvu{,.bk}
に展開され、cp
*.djvu
*.djvu.bk
次にそれぞれ1つが拡張されます。ワイルドカードを含めるワイルドカードが1つ以上のファイルと一致すると、単語は拡張されます。一致するファイルはありますが、*.djvu
一致するファイルが*.djvu.bk
ないためcp
a.djvu
b.djvu
*.djvu.bk
。
一致するファイルがある場合、*.djvu.bk
このワイルドカードパターンも拡張されるため、次のような結果になりますcp
a.djvu
b.djvu
a.djvu.bk
c.djvu.bk
。ファイルを扱うことが目的ですが、cp
どちらのパターンも一致しないようにする場合は、kshを使用できます。拡張パターン:*.djvu
*.djvu.bk
shopt -s extglob
cp *.djvu?(.bk) somedir/
しかし、それはあなたがしたいことではありません。引数を拡張して欲しいものを得ることはできません。各ファイルに対して、それぞれ正しいターゲットを使用して別々のコマンドを実行するcp
必要があります。 1つのコマンドで十分な唯一のケースは、ファイルが1つだけなので、単一のファイルに拡張される場合です。この場合、コマンドを入力する最も簡単な方法は、モードに入り(入力を開始)、bashに+を押して展開し、を押して末尾のスペースを削除してEnterを押すように指示することです。cp
.djvu
cp
.djvu
*.djvu
cp *.djvu
CtrlX *Backspace{,.bk}
複数のファイルをコピーするには、cp
何らかの方法で呼び出しを繰り返すか、名前パターンに基づいてファイルをコピーできる他のツールを使用する必要があります。
Bashでループを書くのはとても簡単です。
for x in *.djvu; do cp "$x" "$x.bk"; done
使用できる別のツールは次のとおりです。公園。ここに入力するのはあまり楽しくありません。
pax -rw -s'/$/.bk/' *.djvu .
Zshはゼロこの種の仕事のために。次の場所にロードしてください.zshrc
。
autoload -U zmv
alias zcp='zmv -C' zln='zmv -L'
その後実行
zcp '*.djvu' '$f.bk'