我有一个带文件的目录
heat1.conf
heat2.conf
...
heat<n>.conf
minimize.conf
...
other files....
我希望我的 Bash脚本能够获取最高编号的文件名(因此我可以在找到错误条件时删除并替换它)。
实现这一目标的最佳方法是什么?
请讨论解决方案的速度以及您认为这是最佳方法的原因。
答案 0 :(得分:6)
如果您要仅在当前目录中列出您的文件,则无需使用find with maxdepth 1或使用ls
。只需使用带有shell扩展的for循环。此外,expr
是外部的。如果你的号码不包含小数,你可以使用bash自己的比较。
max=-1
for file in heat*.conf
do
num=${file:4}
num=${file%.conf}
[[ $num -gt $max ]] && max=$num
done
echo "max is: $max"
答案 1 :(得分:3)
怎么样:
max=$(find . -name 'heat[1-9]*.conf' -depth 1 |
sed 's/heat\([0-9][0-9]*\)\.conf/\1/' |
sort -n |
tail -n 1)
列出可能的文件名;只保留非数字位;排序数字;选择最大(最后)的数字。
关于速度:没有像Perl(Python,Ruby,...)这样的脚本语言,这就像你能得到的一样好。使用find
代替ls
意味着文件名列表只生成一次(此答案的第一个版本使用ls
,但这会导致shell生成列表文件名,然后ls
来回显该列表)。 sed
命令非常简单,并生成一个必须排序的数字列表。您可以争辩说,以sort -nr
传送到sed 1q
的反向数字顺序排序会更快;第二个sed
将读取较少的数据,并且排序可能不会在sed
关闭其输入(因为它终止)的SIGPIPE之前生成所有输出。
在像Perl这样的脚本语言中,您可以避免多个进程,以及这些进程之间管道通信的开销。这会更快,但涉及的shell脚本要少得多。
答案 2 :(得分:0)
我提出了一个解决方案:
highest=-1
current_dir=`pwd`
cd $my_dir
for file in $(ls heat*) ; do #assume I've already checked for dir existence
if [ "${file:4:$(($(expr length $file)-9))}" -gt "$highest" ]; then
highest=${file:4:$(($(expr length $file)-9))}
fi
done
cd $current_dir
....好的,我接受了你的建议并编辑了我的解决方案来废弃expr并预先保存变量。在1000次试验中,我的方法(修改)平均比Jon更慢,但比GhostDog慢,但标准偏差相对较大。
我的修改后的脚本在我的试用版中如下所示,Jon和Ghost Dog的解决方案......
declare -a timing
for trial in {1..1000}; do
res1=$(date +%s.%N)
highest=-1
current_dir=`pwd`
cd $my_dir
for file in $(ls heat*) ; do
#assume I've already checked for dir existence
file_no=${file:4:${#file}-9}
if [ $file_no -gt $highest ]; then
highest=$file_no
fi
done
res2=$(date +%s.%N)
timing[$trial]=$(echo "scale=9; $res2 - $res1"|bc)
cd $current_dir
done
average=0
#compile net result
for trial in {1..1000}; do
current_entry=${timing[$trial]}
average=$( echo "scale=9; (($average+$current_entry/1000.0))"|bc)
done
std_dev=0
for trial in {1..1000}; do
current_entry=${timing[$trial]}
std_dev=$(echo "scale=9; (($std_dev + ($current_entry-$average)*($current_entry-$average)))"|bc)
done
std_dev=$(echo "scale=9; sqrt (($std_dev/1000))"|bc)
printf "Approach 1 (Jason), AVG Elapsed Time: %.9F\n" $average
printf "STD Deviation: %.9F\n" $std_dev
for trial in {1..1000}; do
res1=$(date +%s.%N)
highest=-1
current_dir=`pwd`
cd $my_dir
max=$(ls heat[1-9]*.conf |
sed 's/heat\([0-9][0-9]*\)\.conf/\1/' |
sort -n |
tail -n 1)
res2=$(date +%s.%N)
timing[$trial]=$(echo "scale=9; $res2 - $res1"|bc)
cd $current_dir
done
average=0
#compile net result
for trial in {1..1000}; do
current_entry=${timing[$trial]}
average=$( echo "scale=9; (($average+$current_entry/1000.0))"|bc)
done
std_dev=0
for trial in {1..1000}; do
current_entry=${timing[$trial]}
#echo "(($std_dev + ($current_entry-$average)*($current_entry-$average))"
std_dev=$(echo "scale=9; (($std_dev + ($current_entry-$average)*($current_entry-$average)))"|bc)
done
std_dev=$(echo "scale=9; sqrt (($std_dev/1000))"|bc)
printf "Approach 2 (Jon), AVG Elapsed Time: %.9F\n" $average
printf "STD Deviation: %.9F\n" $std_dev
for trial in {1..1000}; do
res1=$(date +%s.%N)
highest=-1
current_dir=`pwd`
cd $my_dir
for file in heat*.conf
do
num=${file:4}
num=${file%.conf}
[[ $num -gt $max ]] && max=$num
done
res2=$(date +%s.%N)
timing[$trial]=$(echo "scale=9; $res2 - $res1"|bc)
cd $current_dir
done
average=0
#compile net result
for trial in {1..1000}; do
current_entry=${timing[$trial]}
average=$( echo "scale=9; (($average+$current_entry/1000.0))"|bc)
done
std_dev=0
for trial in {1..1000}; do
current_entry=${timing[$trial]}
#echo "(($std_dev + ($current_entry-$average)*($current_entry-$average))"
std_dev=$(echo "scale=9; (($std_dev + ($current_entry-$average)*($current_entry-$average)))"|bc)
done
std_dev=$(echo "scale=9; sqrt (($std_dev/1000))"|bc)
printf "Approach 3 (GhostDog), AVG Elapsed Time: %.9F\n" $average
printf "STD Deviation: %.9F\n" $std_dev
......结果是:
Approach 1 (Jason), AVG Elapsed Time: 0.041418086
STD Deviation: 0.177111854
Approach 2 (Jon), AVG Elapsed Time: 0.061025972
STD Deviation: 0.212572411
Approach 3 (GhostDog), AVG Elapsed Time: 0.026292145
STD Deviation: 0.145542801
干得好GhostDog !!!感谢Jon和评论者提供的建议! :)
答案 3 :(得分:0)
您可以像这样使用sort --version-sort
ls heat*.conf | sort -r --version-sort | head -1