0

我知道这是一个愚蠢的问题,甚至可能与 awk 本身无关(更像是 shell),但让我解释一下我需要什么:我想要(是的,这段代码是错误的,但我希望你能明白)

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 的输出是字符串拆分和全局扩展的;它不能引用带空格的文件名,如果它引用一个名为 的文件*,它将被 shell 替换为当前目录中所有文件的列表;其他 glob 表达式也类似地展开。不要这样做。


Doing this safely with awk is hard without a substantial number of lines of bash wrapping it, because doing it safely requires generating a NUL-delimited list of files (which awk can do), reading that list out of awk into a shell array, and then expanding it into an argument list.

#!/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[@]}" ../

The list needs to be NUL-delimited because NULs are the only characters which cannot legitimately exist in a literal filename; newlines, glob characters, and everything else is valid (/ isn't valid within a filename proper, but as the path separator, it's entirely valid within a fully-qualified path) -- and the shell doesn't have tools for expanding such lists without multiple lines of code involved.

That said, you don't need awk at all for your example:

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

...or, to mimic your awk script's logic in native bash:

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