不安全地这样做很容易:
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[@]}" ../