我很不幸拥有 MS-DOS 背景 - 但至少它让我体会到 Linux 的强大程度。我一直在努力让我的 Linux-Fu 达到标准,但是有一些可以用 DOS 完成的事情我不确定如何完成最容易对于Linux:
重命名多个文件 - 使用两个通配符
c:\> dir
Directory of c:\
file1.txt
file2.txt
file3.txt
file4.txt
c:\>rename *.txt *.bak
c:\> dir
Directory of c:\
file1.bak
file2.bak
file3.bak
file4.bak
我知道我可以find -exec
在这里使用,但可以使用更短的语法 - 也许mv
带有一些特殊的标志或语法?我想这的关键是第二 *
通配符作为linux不应该对第一个有问题(即我知道如何选择我想使用通配符重命名的文件)
重命名单个文件 - 使用一个通配符
c:\> dir
Directory of c:\
file1.txt
c:\>rename file1.txt *.bak
c:\> dir
Directory of c:\
file1.bak
当重命名又长又笨重的文件名时,这将特别有用。我想也许我可以用它mv file1.txt $1.bak
来结束file1.txt.bak
也可以接受,但我不确定您是否可以引用$1
与 shell 命令内联的参数。同样,在这种特殊情况下,ms-dos 如何将*
通配符混为一谈,将其用作文件名部分的捕获/替换匹配,这很方便。
使用通配符过滤目录列表
c:\> dir
Directory of c:\
file1.txt
file2.txt
file3.txt
file4.txt
text.txt
\temp (directory)
c:\> dir file*
Directory of c:\
file1.txt
file2.txt
file3.txt
file4.txt
c:\> t*
Directory of c:\
text.txt
\temp (directory)
我不确定这样做的正确语法ls
是什么,或者是否可能。如果我做了类似的事情,ls t*
它将递归到以t
.我的解决方法是使用find . --max-depth 1 -iname "t*"
或类似的东西ls -al | grep t
- 这两种方法都不像dir t*
现在那么短和简单。
最后,我知道我可以设置别名来缩短这些长命令,但我想学习一些开箱即用的 linux-fu 来完成这些事情,因为有时你会连接到远程系统或工作在新机器上。
那么我怎样才能像以前一样使用文件mv
操作呢?ls
dir
rename
答案1
Windows 和 POSIX shell 之间的根本区别之一cmd
是谁负责通配符扩展。 Shell 在启动您要求的实际命令之前执行所有所需的扩展。cmd
大多将通配符模式不加修改地传递给命令。(我说大多数,因为我认为有例外,并且环境变量在大多数情况下都会被扩展。)这使得编写与 中rename
相同的语法一起工作的程序变得cmd
相当棘手。
但是有一个rename
针对 Linux 的 - 具有完全不同的参数,请查看手册页(在我的系统上有点简洁,并且rename
来自util-linux
我系统上的软件包,应该广泛使用)。您的第一次重命名将像这样完成:
rename .txt .bak *.txt
请注意,shell 执行了*
扩展,因此rename
它本身实际上认为它是这样调用的:
rename .txt .bak file1.txt file2.txt file3.txt ...
所以你可以猜测单个文件版本:
rename .txt .bak file1.txt
如果您不想使用rename
而是自己实现它,您可以为此创建一个函数。假设您只想更改文件扩展名,对于单个文件重命名,请查看以下内容:
$ function chext() {
newext="$1"
file="$2"
newfile="${file%.*}$newext"
echo mv "$file" "$newfile"
}
$ chext .csv test.txt
mv text.txt text.csv
$newfile
是使用一个构建的子串删除删除原始扩展名,然后连接新扩展名。您可以扩展该功能以相对轻松地处理多个文件。
至于你的ls
问题,请使用-d
开关。这将阻止ls
列出目录的内容。
演示:
$ ls -al
total 536
drwx------ 3 owner users 528384 Jan 7 17:29 .
drwxr-xr-x 126 owner users 12288 Jan 7 17:26 ..
-rw-r--r-- 1 owner users 0 Jan 7 17:28 f1.csv
-rw-r--r-- 1 owner users 0 Jan 7 17:28 f2.csv
-rw-r--r-- 1 owner users 0 Jan 7 17:28 f3.csv
-rw-r--r-- 1 owner users 0 Jan 7 17:28 f4.csv
drwxr-xr-x 2 owner users 4096 Jan 7 17:33 test
-rw-r--r-- 1 owner users 0 Jan 7 17:27 test.csv
通配符重命名
$ rename .csv .txt f*
$ ls -al
total 536
drwx------ 3 owner users 528384 Jan 7 17:34 .
drwxr-xr-x 126 owner users 12288 Jan 7 17:26 ..
-rw-r--r-- 1 owner users 0 Jan 7 17:28 f1.txt
-rw-r--r-- 1 owner users 0 Jan 7 17:28 f2.txt
-rw-r--r-- 1 owner users 0 Jan 7 17:28 f3.txt
-rw-r--r-- 1 owner users 0 Jan 7 17:28 f4.txt
drwxr-xr-x 2 owner users 4096 Jan 7 17:33 test
-rw-r--r-- 1 owner users 0 Jan 7 17:27 test.csv
单个文件重命名
$ rename .txt .csv f1.txt
$ ls -al
total 536
drwx------ 3 owner users 528384 Jan 7 17:34 .
drwxr-xr-x 126 owner users 12288 Jan 7 17:26 ..
-rw-r--r-- 1 owner users 0 Jan 7 17:28 f1.csv
-rw-r--r-- 1 owner users 0 Jan 7 17:28 f2.txt
-rw-r--r-- 1 owner users 0 Jan 7 17:28 f3.txt
-rw-r--r-- 1 owner users 0 Jan 7 17:28 f4.txt
drwxr-xr-x 2 owner users 4096 Jan 7 17:33 test
-rw-r--r-- 1 owner users 0 Jan 7 17:27 test.csv
默认ls
$ ls -l t*
-rw-r--r-- 1 owner users 0 Jan 7 17:27 test.csv
test:
total 0
-rw-r--r-- 1 owner users 0 Jan 7 17:33 dont_show_me_please
ls
不检查目录
$ ls -ld t*
drwxr-xr-x 2 owner users 4096 Jan 7 17:33 test
-rw-r--r-- 1 owner users 0 Jan 7 17:27 test.csv
答案2
谈到通配符时要记住的一件事是它们是由 shell 扩展的。应用程序不知道您是否使用了通配符或键入了名称。例如,如果您键入rename *.txt *.bak
,则该rename
命令会看到类似 的内容rename file1.txt file2.txt existingfile.bak
。这些信息还不足以继续下去。
我先解决这个问题ls
,因为它更简单。如果您想要的只是匹配的名称,那么您不需要ls
,因为 shell 已经在进行扩展。
echo t*
如果您想要有关文件的更多信息,请将选项传递-d
给ls
,告诉它不要列出目录的内容。
ls -ld t*
没有用于重命名文件的标准实用程序,因为第一个 UNIX 系统没有附带该实用程序。重命名文件的可移植方法使用循环,并且有点冗长:
for x in *.txt; do mv -- "$x" "${x%.txt}.bak"; done
有几个常用的实用程序可以重命名文件,但都不能保证在给定的 UNIX 系统上安装它们,但它们都很容易安装。以下是主要的:
rename
来自该util-linux
套件,可在每个非嵌入式 Linux 系统(而不是其他系统)上使用。在 Debian 及其衍生版本(包括 Ubuntu)上,此命令称为rename.ul
.如果.txt
除了最后的扩展名之外没有出现任何其他的情况,你可以写rename .txt .bak *.txt
rename
是一个 Perl 脚本,Debian 及其衍生版本以/usr/bin/rename
.您可以根据任意 Perl 命令重命名文件。rename 's/\.txt\z/\.bak/' *.txt
mmv
,它可以根据几种基于名称的模式重命名、复制和链接文件,并且有许多与目标名称已存在时发生的情况相关的选项。请注意,必须使用引号来防止通配符被 shell 扩展。mmv '*.txt' '#1.txt'
zmv
是一个桀骜函数,当且仅当您的 shell 是 zsh 时才可用。它可以匹配任意 zsh 模式(因此您可以根据任意正则表达式匹配文件名,而不仅仅是通配符,并且您可以根据其他条件(例如日期和大小)匹配文件)。zmv
也可以复制和链接。zmv '(*).txt' '$1.txt'
如果您对所使用的机器有一定的控制权,我的建议是使用 zsh 作为您的 shell(它比 bash 有其他好处)并将这些行放入您的~/.zshrc
:
autoload -U zmv
alias zmv='noglob zmv -w'
alias zcp='zmv -C'
alias zln='zmv -L'
alias zsy='zmv -Ls'
noglob
是 zsh 的一项功能,告诉 shell 不要在命令参数中扩展通配符。这样您就可以编写zmv *.txt \$1.txt
(您始终需要保护$
替换文本中的 )。