我正在尝试更改开头带有点和空格且结尾处缺少点的 jpg 文件(如下. Startjpg
所示Start.jpg
该点使文件隐藏sed
并ls -al
列出这些文件,因此我通过管道传输ls -al
到sed
.我在网上读了很多手册,但总是遇到这个错误
sed: -e expression #1, char 6: unknown command: `/'
我试过了
ls -al | sed -r '/^\./*.*/g'
ls -al | sed -r '/^\.//g'
ls -al | sed -r '/.*/[\.]g'
ls -al | sed 's/^\./\\1*./g'
还有更多,甚至更多更多。
我还需要将 filejpg 更改为 file.jpg
答案1
使用 Perlrename
工具(在 Debian 和包括 Ubuntu 在内的朋友上调用该工具rename
,它可能prename
在其他地方):
rename -n 's/(?<!\.)jpg$/.jpg/' * # -n makes it show you what it'll do,
# but not actually do it. Remove the -n to
# actually rename
分解一下这个模式:jpg$
意思是“以‘jpg’结尾”。意思(?<!\.)
是“在‘jpg’之前没有点”。这会阻止你变成foo.jpg
,foo..jpg
这是愚蠢的。
是*
普通的 shell 通配符;rename
获取要考虑重命名的文件列表。您当然可以这样做/path/to/dir/*
,传递文件名列表,与 结合使用find
等。
从一开始删除点和空格也相当容易:
rename -n 's/^[. ]+//' * # trying -n first is good practice
这将删除开头的所有点和空格。就会. . . foo
变成foo
.
通常,*
shell 扩展不会产生名称以点开头的文件(隐藏文件)。一种选择是使用.*
;这还将产生两个特殊条目.
(当前目录)和..
(父目录)。在这种情况下这应该是无害的;第一个命令将忽略它们(它们不以 结尾jpg
);第二个命令将尝试重命名它们,但这应该只会产生错误。另一种选择是找到:
find -type f -exec rename -n 's/^[. ]+//' '{}' +
-type f
将仅限于文件。当然,您也可以使用 find 的任何其他选项。
答案2
虽然sed
它是一个非常有用且多功能的工具,但您没有正确使用它。它最适合用于匹配和替换文本文件中的字符串;它不能直接重命名文件系统上的文件。
此任务更适合 bash 单行代码(假设这是您的 shell)。要重命名类似. filejpg
to 的内容file.jpg
,请使用以下命令:
find . -name '. *' -print0 | while read -d $'\0' file; do short_file=${file%jpg}.jpg; mv "$file" "${short_file:4}"; done
解释
find
是一个返回与特定文件属性(在本例中为文件名)匹配的文件路径的程序。如果您只想知道当前路径的子目录中的 .jpg 文件是什么,您可以这样做find . -name "*.jpg"
。通常这会在新行上输出每个文件。这-print0
使得它用空字符分隔匹配项。当我们将输出传递给下一个命令时,这允许正确处理带有空格的文件名。
该|
角色被称为管道。它告诉 shell 获取左侧命令的输出并将其作为右侧命令(在本例中为循环read
内的命令)的输入传递while
。
该read
命令用于获取的输出find
并将其分配给变量file
。通常,这会file
一次为每个单词分配值,但是-d $'\0'$
会导致分配由空字符分隔(find
与我们使用-print0
标志分隔文件的方式相匹配)。
while 循环会导致read
为每个匹配的文件名迭代地为“file”分配值。和do
是done
while 循环的标准 bash 语法的一部分:
while <something is true>; do
<run some commands>
done
在这种情况下,我们的“运行一些命令”首先修复文件名的扩展名并将其分配给一个新变量:short_file=${file%jpg}.jpg
更改. filejpg
为. file.jpg
.然后它运行mv
以重命名该文件,删除.
扩展名更正的文件名开头的:mv "$file" ${short_file:2}
。
答案3
作为其他答案的替代方案,您可以使用图形工具GP重命名。它可以替换字符、截断文件名等。优点是有一个内置的预览功能,可以在重命名新文件名之前检查它们。但由于它一次只能作用于一个目录,因此在子文件夹中的多个文件夹中使用它会很不方便。但对于少于 10 个文件夹来说这不是问题。