有时我需要重命名一些文件,例如添加前缀或删除某些内容。 起初我写了一个python脚本。它运作良好,我想要一个shell版本。因此我写了类似的东西:
$ 1 - 要列出的目录, 2美元 - 将替换什么样的模式, 3美元 - 更换。
echo "usage: dir pattern replacement"
for fname in `ls $1`
do
newName=$(echo $fname | sed "s/^$2/$3/")
echo 'mv' "$1/$fname" "$1/$newName&&"
mv "$1/$fname" "$1/$newName"
done
它的工作原理非常缓慢,可能是因为它需要创建一个进程(此处为sed
和mv
)并将其销毁并再次创建相同的进程以获得不同的参数。真的吗?如果是这样,如何避免它,我怎样才能获得更快的版本?
我想为所有已处理的文件提供一个名称(使用sed
一次处理它们),但它仍然需要循环中的mv
。
请告诉我,你们是怎么做到的?谢谢。如果你发现我的问题很难理解,请耐心等待,我的英语不是很好,对不起。
---更新---
对不起我的描述。我的核心问题是:“如果我们应该在循环中使用一些命令,那会降低性能吗?”因为在for i in {1..100000}; do ls 1>/dev/null; done
中创建和销毁一个过程将占用大部分时间。所以我想要的是“有没有办法降低成本?”。
感谢kev和S.R.I为我提供了rename
重命名文件的解决方案。
答案 0 :(得分:2)
每当你调用一个外部二进制文件(ls
,sed
,mv
)时,bash必须自行执行命令,这会对性能造成重大影响。
你可以在纯粹的bash 4.X中做你想做的一切,只需要拨打mv
pat_rename(){
if [[ ! -d "$1" ]]; then
echo "Error: '$1' is not a valid directory"
return
fi
shopt -s globstar
cd "$1"
for file in **; do
echo "mv $file ${file//$2/$3}"
done
}
答案 1 :(得分:1)
最简单的第一个。 rename
出了什么问题?
mkdir tstbin
for i in `seq 1 20`
do
touch tstbin/filename$i.txt
done
rename .txt .html tstbin/*.txt
或者您使用的是旧的* nix机器?
答案 2 :(得分:0)
为了避免在每个文件上重新执行sed,您可以改为设置两个名称流,一个原始文件,一个转换,然后从末端啜饮:
exec 3< <(ls)
exec 4< <(ls | sed 's/from/to/')
IFS=`echo`
while read -u3 orig && read -u4 to; do
mv "${orig}" "${to}";
done;
答案 3 :(得分:0)
我认为您可以将所有文件名存储到文件或字符串中,并使用awk和sed执行一次而不是逐个执行。