0

I am working with a Ethernet camera that comes with Busybox.
A single board computer is connected to it through RS232. The SBC needs to send a single command to the camera in order to take a jpg snapshot, save it to a CF memory card and name it in a sequential order (0001, 0002 etc..).
This is the code I use to take a single snapshot, without sequential naming:

wget http://127.0.0.1/snap.php -O /mnt/0/snapfull`date +%d%m%y%H%M%S`.jpg

I need the files to be named sequentially. This is the code I found here that does a sequential renaming for files already existing, but I noted that when the code is executed once more after the renaming of multiple files, cross-renaming can lead to file deletion (I ran the code when files from 0001.jpg to 0005.jpg were present in the dir, and file 0004.jpg was deleted because the find cmd listed file 0005 before file 0004, so it cross-renamed both and file 0004 was deleted.)

find . -name '*.jpg' | awk 'BEGIN{ a=0 }{ printf "mv %s %04d.jpg\n", $0, a++ }' | dash

What I am looking for, is a single shell script that can be requested multiple times per day by the SBC, so that the camera takes the picture, save it and name it in a sequential order, based on the last number used (if the latest file is 0005.jpg, next picture will be named 0006.jpg).
It would be great to add this naming capability in the fisrt line of code I attached, so that I can include it in a sh script that can be called by the SBC.

Community
  • 1
  • 1
Rick
  • 45
  • 9
  • Why is this tagged bash, if you're using either a busybox-provided shell (which, best-case, may be ash) or explicitly invoking dash? – Charles Duffy Dec 03 '14 at 15:22
  • 1
    Also, using awk to generate shell commands in that way is a very, very bad practice. Think about what happens if you have a file named `$(rm -rf /).jpg`. (Of course, the `/` needs to be a directory separator, but since you're doing a recursive find, that will still work). – Charles Duffy Dec 03 '14 at 15:24
  • Reading the linked SO answer, I'm somewhat aghast at how many "answers" were given with that and other vulnerabilities and bugs. The accepted one only needed additional quoting to be safe, though, and I've edited it to be fixed appropriately. – Charles Duffy Dec 03 '14 at 15:29
  • Charles, thanks for the comments. Sorry for the bash tag, it was a typo. – Rick Dec 03 '14 at 15:32
  • Every time your script is run, do you want it to take a series of snapshots starting at 0001 (which is what the answer you gave is more tuned to), or should it find the current most recent number and add a new snapshot immediately after it? – Charles Duffy Dec 03 '14 at 15:39
  • Exactly like you said: find the most recent number, and rename the new snapshot just made according to that number. So if the latest file is 0005.jpg, the new file should be saved as 0006.jpg . – Rick Dec 03 '14 at 15:42
  • @shellter Actually I cannot leave the date, although that would be easier. The SBC needs sequential files in order to process them. The date is kept in the jpg EXIF info. – Rick Dec 03 '14 at 19:13

2 Answers2

1

This is the code I'm actually testing and seems to be working, based on @Charles answer:

#!/bin/sh
set -- *.jpg             # put the sorted list of picture namefiles on argv ( the number of files on the list can be requested by echo $# ) 
while [ $# -gt 1 ]; do   # as long as the number of files in the list is more than 1 ...
  shift                  # ...some rows are shifted until only one remains
done
if [ "$1" = "*.jpg" ]; then   # If cycle to determine if argv is empty because there is no jpg      file present in the dir.
  set -- snapfull0000.jpg     # argv is set so that following cmds can start the sequence from 1 on.
else
  echo "More than a jpg file found in the dir."
fi

num=${1#*snapfull}                     # 1# is the first row of $#. The alphabetical part of the filename is removed.
num=${num%.*}                          # Removes the suffix after the name.
num=$(printf "%04d" "$(($num + 1))")   # the variable is updated to the next digit and the number is padded (zeroes are added) 

wget http://127.0.0.1/snapfull.php -O "snapfull${num}.jpg" #the snapshot is requested to the camera, with the sequential naming of the jpeg file.
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Rick
  • 45
  • 9
  • FWIW, the `$((num+1))` as opposed to `$(($num + 1 ))` wasn't a typo -- on a POSIX-compliant shell, the inner `$` shouldn't be necessary. – Charles Duffy Dec 04 '14 at 20:58
  • I tried once more the format you suggest, but I keep getting an error. I am also having another issue with the sequence stopping, which you can see [here](http://stackoverflow.com/questions/27324506/issue-with-sequential-file-saving-and-naming). – Rick Dec 05 '14 at 20:55
0

This will work if and only if your filenames are all identical except for the numeric part, and the numeric part is padded enough that they're all the same number of digits.

set -- *.jpg           # put the sorted list of names on argv
while [ $# -gt 1 ]; do # as long as there's more than one...
  shift                # ...pop something off the beginning...
done
num=${1#*snapfull}                  # trim the leading alpha part of the name
num=${num%.*}                       # trim the trailing numeric part of the name
printf -v num '%04d' "$((num + 1))" # increment the number and pad it out

wget http://127.0.0.1/snap.php -O "snapfull${num}.jpg"
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • Thanks for your effort! This is the error I get `./snap3.sh: 10: arith: syntax error: "num + 1"` I've put the script in the dir where the files are supposed to be saved. When I put the script in the /bin, how do I specify the path in the snapshot code? Something like this? `wget http://127.0.0.1/snapfull.php -O /mnt/0/"snapfull${num}.jpg"` – Rick Dec 03 '14 at 19:07
  • @Rick, what's your shell? `$(( num + 1 ))` is valid in any POSIX sh compliant shell, assuming that `num` was correctly stripped to be a valid number. I'd suggest testing to be sure that the stripping worked correctly, ie. echo'ing the value. – Charles Duffy Dec 03 '14 at 20:35
  • As for the path -- other parts of this code won't work correctly if the current directory isn't the location with the output files, which is why I'm assuming that you've put a `cd /mnt/0` earlier in your script. – Charles Duffy Dec 03 '14 at 20:36
  • It's a Bourne Shell. There were just minor issues with the formatting of the variables. I added an if cycle to check whether the argv is empty when there's no jpg present. Thanks a lot @Charles for your precious answer! – Rick Dec 04 '14 at 18:11
  • @Rick, much of the functionality given here (like `$(( ))` for math contexts) is POSIX sh (from the early 90s), not Bourne (from the 70s). They're not the same thing, and `/bin/sh` is only very rarely Bourne (the only operating system vendor I know of who's released a non-POSIX `/bin/sh` inside the last decade is Sun). That pedantry aside, I'm glad to hear this answer was helpful! – Charles Duffy Dec 04 '14 at 20:56
  • You're right @Charles , it's an ash shell. Unfortunately Busybox doesn't come with that much info. There's also a dash shell available. – Rick Dec 05 '14 at 01:45