Reputation: 3075
I have a directory with files that look like this:
001_something.php 002_something_else.php
004_xyz.php 005_do_good_to_others.php
I ultimately want to create a new, empty PHP file whose name starts with the next number in the series.
LIST=`exec ls $MY_DIR | sed 's/\([0-9]\+\).*/\1/g' | tr '\n' ' '`
The preceding code gives me a string like this:
LIST='001 002 004 005 '
I want to grab that 005, increment by one, and then use that number to generate the new filename. How do I do that in BASH?
Upvotes: 13
Views: 16262
Reputation: 11
I post this answer to propose a minimal solution to the core question "Find highest numbered filename in a directory where names start with digits":
ls -1 "$MyDir" | sort -hr | head -n 1
The first statement puts out the files in MyDir as one liners with the -1 option. This is piped to the sort function which sorts in human numeric order with -h and in reverse order (highest number first) with -r. This is piped to the head function which just delivers the -n top most results (1 in the example). The answer considers human numeric sort order i.e. 221 is higher than 67. It is a POSIX shell solution so highly compatible.
Upvotes: 1
Reputation: 342363
touch "newfile_$(printf "%03d" $(echo $(ls 00?_*.php|sed 's/_.*//'|sort -rn|head -1)+1|bc))"
2.
num=$(ls 00?*.php|sed 's/.*//'|sort -rn|head -1) touch $(printf "newfile_%03d" $((num+1)))
Upvotes: 1
Reputation: 67221
This seems to be more simple.
ls [0-9]* | sort -rn | awk '{FS="_"; printf "%03d_new_file.php\n",$1+1;exit}'
Upvotes: 3
Reputation: 15582
Using only standard tools, the following will give you the prefix for the new file (006):
ls [0-9]* | sed 's/_/ _/' | sort -rn | awk '{printf "%03d", $1 + 1; exit}'
Upvotes: 8
Reputation: 360055
Fast, subshell-free and loop-free (also handles filenames with spaces)*:
list=([0-9]*)
last=${list[@]: -1}
nextnum=00$((10#${last%%[^0-9]*} + 1))
nextnum=${nextnum: -3}
touch ${nextnum}_a_new_file.php
Given your example files the output would be:
006_a_new_file.php
Upvotes: 2
Reputation: 146043
$ LIST=($LIST)
$ newfile=`printf %03d-whatever $((10#${LIST[${#LIST}]}+1))`
$ echo $newfile
006-whatever
So, that's bash-specific. Below is a any-posix-shell-including-bash solution, tho I imagine something simpler is possible.
$ cat /tmp/z
f () {
eval echo \${$#} | sed -e 's/^0*//'
}
LIST='001 002 004 005 '
newname=`printf %03d-whatever $(($(f $LIST) + 1))`
echo $newname
$ sh /tmp/z
006-whatever
$
Upvotes: 10
Reputation: 6248
Do you need the whole LIST?
If not
LAST=`exec ls $MY_DIR | sed 's/\([0-9]\+\).*/\1/g' | sort -n | tail -1`
will give you just the 005 part and
printf "%03d" `expr 1 + $LAST`
will print the next number in the sequence.
Upvotes: 16
Reputation: 342363
$ for file in *php; do last=${file%%_*} ; done
$ newfilename="test.php"
$ printf "%03d_%s" $((last+1)) $newfilename
006_test.php
i leave it to you to do the creation of new file
Upvotes: 1
Reputation:
Here's a solution (you need bc):
#!/bin/bash
LIST='001 002 008 005 004 002 '
a=0
for f in $LIST
do
t=$(echo $f + 1|bc)
if [ $t -ge $a ]
then
a=$t
fi
done
printf "%03d\n" $a
Upvotes: 0