0

これはばかげた質問であり、awk 自体 (シェルのようなもの) とは関係がないこともわかっていますが、必要なものを説明させてください:

mv [awk 'BEGIN{for (i = 1; i <= 3; i++) { printf("file%d.png ", i) }}'] ../

私が入ったかのように解釈される

mv file1.png file2.png file3.png ../

基本的に、アスタリスクのようなもの

mv file*.png ../

します。

前もって感謝します。

4

1 に答える 1

1

これを危険にさらすのは簡単です:

mv $(awk 'BEGIN{for (i = 1; i <= 3; i++) { printf("file%d.png ", i) }}') ../

ただし、これは危険で安全ではありません。awk の出力は、文字列分割およびグロブ展開です。スペースを含むファイル名を参照することはできません。 という名前のファイルを参照する場合*、これはシェルによって現在のディレクトリ内のすべてのファイルのリストに置き換えられます。他のグロブ式も同様に展開されます。やらないでください。


これを awk で安全に行うのは、かなりの数の bash でラップする必要があるため困難です。安全に行うには、NUL で区切られたファイルのリストを生成し (awk で実行できます)、そのリストを awk からシェル配列に読み込む必要があるためです。次に、それを引数リストに展開します。

#!/bin/bash
# ^^ arrays are bash features, so a script starting with #!/bin/sh will not work
#    even if /bin/sh is a symlink to /bin/bash, #!/bin/sh will disable some
#    bash-only extensions.
awk_files=()
while IFS='' read -r -d '' file; do
  awk_files+=( "$file" )
done < <(awk 'BEGIN{for (i = 1; i <= 3; i++) { printf("file%d.png\0", i) }}')
mv "${awk_files[@]}" ../

リストは NUL で区切られている必要があります。NUL は、リテラル ファイル名に正当に存在できない唯一の文字だからです。改行、グロブ文字、およびその他すべてが有効です (/適切なファイル名内では有効ではありませんが、パス区切り文字として、完全修飾パス内では完全に有効です)。シェルには、そのようなリストを展開するためのツールがありません。複数行のコードを使用する必要はありません。

つまり、あなたの例では awk はまったく必要ありません:

mv file{1..3}.png ../

...または、ネイティブ bash で awk スクリプトのロジックを模倣するには:

files=()
for ((i=1; i<=3; i++)); do
  files+=( "file${i}.png" )
done
mv "${files[@]}" ../
于 2013-03-29T18:41:40.130 に答える