Linux 如何使用“更改”更改文件类型的扩展名;查找“;和Bash一起?

Linux 如何使用“更改”更改文件类型的扩展名;查找“;和Bash一起?,linux,bash,shell,unix,scripting,Linux,Bash,Shell,Unix,Scripting,用户输入他们要查找的文件类型;它存储在$arg1中;他们要更改的文件类型存储为$arg2。我能够找到我要找的,但我不确定如何保持文件名不变,只是改变类型。。。例如,file1.txt进入file1.log find . -type f -iname "*.$arg1" -exec mv {} \; 我想这样做: find . -type f -iname "*.$arg1" -print0 |\ while IFS= read -r -d '' file; do m

用户输入他们要查找的文件类型;它存储在
$arg1
中;他们要更改的文件类型存储为
$arg2
。我能够找到我要找的,但我不确定如何保持文件名不变,只是改变类型。。。例如,
file1.txt
进入
file1.log

find . -type f  -iname "*.$arg1" -exec mv {} \;
我想这样做:

find . -type f  -iname "*.$arg1" -print0 |\
    while IFS= read -r -d '' file; do
        mv -- "$file" "${file%$arg1}$arg2"
    done
我接受了您的
find
命令,并将其输出反馈给
while
循环。在这个循环中,我正在进行实际的重命名。这样,我就可以将文件名作为一个变量,使用bash的字符串操作来操作它。

我会这样做:

find . -type f  -iname "*.$arg1" -print0 |\
    while IFS= read -r -d '' file; do
        mv -- "$file" "${file%$arg1}$arg2"
    done

我接受了您的
find
命令,并将其输出反馈给
while
循环。在这个循环中,我正在进行实际的重命名。通过这种方式,我将文件名作为一个变量,可以使用bash的字符串操作来操作该变量。

要启用的全部功能,可以在
exec
操作中调用
bash-c

find . -type f -iname "*.$arg1" -exec bash -c 'echo mv "$0"  "${0%.*}.$1"' {} "$arg2" \;
我们将
{}
“$arg2”
作为参数添加到
bash-c
,因此它们在命令中可以作为
$0
$1
访问
${0%.*}
删除扩展名,该扩展名将替换为
$arg2
扩展到的任何扩展名

实际上,该命令只打印它将执行的
mv
命令;要实际重命名文件,必须删除
echo


引用是相关的:
bash-c
的参数用单引号引起来,以防止
$0
$1
被过早扩展,而
mv
arg2
的两个参数也被引用来处理其中包含空格的文件名,您可以在
exec
操作中调用
bash-c

find . -type f -iname "*.$arg1" -exec bash -c 'echo mv "$0"  "${0%.*}.$1"' {} "$arg2" \;
我们将
{}
“$arg2”
作为参数添加到
bash-c
,因此它们在命令中可以作为
$0
$1
访问
${0%.*}
删除扩展名,该扩展名将替换为
$arg2
扩展到的任何扩展名

实际上,该命令只打印它将执行的
mv
命令;要实际重命名文件,必须删除
echo


引用是相关的:
bash-c
的参数用单引号引起来,以防止
$0
$1
过早展开,而
mv
的两个参数,和
arg2
也被引用来处理带有空格的文件名。

find-exec bash
思想与
bash
循环思想相结合,您可以使用
-exec
上的
+
终止符告诉
find
将多个文件名传递给bash命令的单个调用。将新类型作为第一个参数传递-它显示在
$0
中,因此可以方便地被
for
循环跳过其余的命令行参数-这样您就有了一个非常有效的解决方案:

find . -type f -iname "*.$arg1" -exec bash -c \
  'for arg; do mv "$arg" "${arg%.*}.$0"; done' "$arg2" {} +
或者,如果您有Linux
rename
命令的任一版本,则可以使用该命令。Perl one(也称为prename,默认安装在Ubuntu和其他基于Debian的发行版上;也可通过
brew安装重命名
从Homebrew获得OS X)可以这样使用:

find . -type f -iname "*.$arg1" -exec rename 's/\Q'"$arg1"'\E$/'"$arg2"'/' {} +
这看起来有点难看,但实际上只是许多UNIX工具中熟悉的
s/old/new/
substitution命令。
$arg1
周围的
\Q
\E
可以防止后缀中的任何奇怪字符被解释为可能与意外内容匹配的正则表达式元字符;
$
后面的
\E
确保模式仅在文件名末尾匹配

默认情况下,在基于Red Hat的Linux发行版(Fedora、CentOS等)上安装的基于模式的版本更简单:

find . -type f -iname "*.$arg1" -exec rename ".$arg1" ".$arg2" {} +

但它也更愚蠢:如果你
rename.com.exe stackoverflow.com_scanner.com
,你会得到一个名为
stackoverflow.exe_scanner.exe
的文件,它将
find-exec bash
思想与
bash
循环思想相结合,您可以使用
-exec
上的
+
终止符告诉
find
将多个文件名传递给bash命令的单个调用。将新类型作为第一个参数传递-它显示在
$0
中,因此可以方便地被
for
循环跳过其余的命令行参数-这样您就有了一个非常有效的解决方案:

find . -type f -iname "*.$arg1" -exec bash -c \
  'for arg; do mv "$arg" "${arg%.*}.$0"; done' "$arg2" {} +
或者,如果您有Linux
rename
命令的任一版本,则可以使用该命令。Perl one(也称为prename,默认安装在Ubuntu和其他基于Debian的发行版上;也可通过
brew安装重命名
从Homebrew获得OS X)可以这样使用:

find . -type f -iname "*.$arg1" -exec rename 's/\Q'"$arg1"'\E$/'"$arg2"'/' {} +
这看起来有点难看,但实际上只是许多UNIX工具中熟悉的
s/old/new/
substitution命令。
$arg1
周围的
\Q
\E
可以防止后缀中的任何奇怪字符被解释为可能与意外内容匹配的正则表达式元字符;
$
后面的
\E
确保模式仅在文件名末尾匹配

默认情况下,在基于Red Hat的Linux发行版(Fedora、CentOS等)上安装的基于模式的版本更简单:

find . -type f -iname "*.$arg1" -exec rename ".$arg1" ".$arg2" {} +

但它也更愚蠢:如果您使用基于
perl
rename.com.exe stackoverflow.com\u scanner.com
,您将得到一个名为
stackoverflow.exe\u scanner.exe
的文件

示例目录:

$ find
.
./a"bn.txt
./t2.abc
./abc
./abc/t1.txt
./abc/list.txt
./a bc.txt
示例参数:

$ arg1='txt'
$ arg2='log'
试运行:

$ find -type f -iname "*.$arg1" -exec rename -n "s/$arg1$/$arg2/" {} +
rename(./a"bn.txt, ./a"bn.log)
rename(./abc/t1.txt, ./abc/t1.log)
rename(./abc/list.txt, ./abc/list.log)
rename(./a bc.txt, ./a bc.log)
正常后删除
-n
选项:

$ find -type f -iname "*.$arg1" -exec rename "s/$arg1$/$arg2/" {} +
$ find
.
./a bc.log
./t2.abc
./abc
./abc/list.log
./abc/t1.log
./a"bn.log

如果您有基于
perl
重命名