我正在重命名一些文件。
这有效:
ls | while IFS= read -r line; do name=$(echo $line | sed -e 's/\(.*\)/\1.jpg/') && mv $line $name; done
没关系,但我想让它更简洁,例如:
ls | while IFS= read -r line; do name=$(sed -e 's/\(.*\)/\1.jpg/' $line) && mv $line $name; done
后一个示例和各种类似的尝试将文件传递到 sed 而不是变量的值。
使用 ˋ $line
ˋ 和$($line)
两者都会导致尝试执行该文件。虽然"$line"
、'line'
with 和 without的变体<
都会导致文件被读入。这是怎么回事?该$line
变量可以直接与 sed 一起使用以实现此目的吗?
答案1
它好像您只想附加.jpg
到当前目录中所有文件名的末尾。如果是这样的话,那么还有更简单的方法:
for f in ./*; do
mv -- "$f" "$f.jpg"
done
确保--
以破折号 ( -
) 开头的文件名不会被解释为mv
.但这在这里不是问题,因为我们还确保通过在循环中使用始终在开头$f
具有路径。./
./*
的输出ls
用于肉眼阅读,通常不适合像您一样发送到 while-read-loop 中。
是的,在第二个示例 ( sed -e 's/\(.*\)/\1.jpg/' $line
) 中,文件的内容将由 读取sed
。而使用 Bash,您就可以做到sed '...' <<<"$line"
这一点。该<<<"string"
构造是一个 Bash 扩展(至少在ksh
和中也可用zsh
),称为“here-string”,它将标准输入上的字符串传递给命令。
答案2
您可以使用这里字符串语法<<<
:
ls | while IFS= read -r line
do
name=$(sed 's/\(.*\)/\1.jpg/' <<< $line) && mv "$line" "$name"
done
请注意,解析 的输出ls
(也不使用不带引号的变量)不被认为是一个好主意。
还有一个工具名称rename
(如果目标只是重命名文件):
rename -n 's/$/.jpg/' *
删除-n
从预览更改为实际重命名的标志。