我正在尝试重命名几个文件。所以我首先需要这些文件名。 我正在使用:
for FILE in $(find . -type f -name "*.flv" -exec basename {} \; ); do
echo "$FILE"
done
当我尝试使用find命令时,它会正确返回文件数,但是当我使用for时,我希望ARQ包含单个文件的整个名称,而是返回分割后的单词文件名。 那么如何获得整个名称,而不仅仅是它的单词呢?
答案 0 :(得分:3)
有几种方法可以让它发挥作用。最简单的是完全使用find exec
:
find . -type f -name "*.flv" -exec bash -c 'f=$(basename "$1"); printf "%s\n" "$f"' _ {} \;
换句话说,如果您愿意,可以在-exec
子句中放置复杂的脚本。
作为第二选择,请考虑这个循环:
find . -name '*.flv' -print0 | while IFS= read -d '' -r file
do
f=$(basename "$file")
printf "%s\n" "$f"
done
答案 1 :(得分:2)
将for
循环与Command Substitution的结果一起使用,不带双引号,默认情况下会导致结果为break on space, tab and newline(默认值为IFS
)。
POSIXly,除了find
和内联脚本之外,您不需要任何其他内容:
$ find . -type f -name "*.flv" -exec sh -c '
for f do
printf "%s\n" "${f##*/}"
done
' sh {} +
使用GNU查找,您不需要内联脚本:
$ find . -type f -name "*.flv" -printf '%f\n'
答案 2 :(得分:1)
查看问题的标题:避免使用in in分割字符串:
不要在循环中使用IFS字段分隔符:
:~> a="sdad asd asda ad
> fdvbdsvf
> dfvsdfv
> 4"
:~> for s in $a; do
echo "== $s ==";
done
== sdad ==
== asd ==
== asda ==
== ad ==
== fdvbdsvf ==
== dfvsdfv ==
== 4 ==
:~> (IFS=; for s in $a; do
echo "== $s ==";
done)
== sdad asd asda ad
fdvbdsvf
dfvsdfv
4 ==
我在最后一个命令中使用了圆括号,因此IFS的更改值仅限于该子进程。
答案 3 :(得分:0)
而不是使用find,
使用rename
命令来重命名多个文件。
例如:
rename 's/foo/bar/' **/*.flv
将文件名中的foo
递归地替换为所有bar
文件中的*.flv
。如果您的shell支持a new globbing option(例如Bash 4.x或zsh),请确保该选项已由shopt -s globstar
启用。
或者,如果您在循环中使用find
,则可以使用:
-print0
(xargs
)等外部程序-0
,-exec cmd
直接在文件({}
)-execdir cmd
在文件所在的目录中执行命令