0

I have some files which have wrong time and date, but the filename contains the correct time and date and I try to write a script to fix this with the touch command.

Example of filename: 071212_090537.jpg

I would like this to be converted to the following format: 1712120905.37

Note, the year is listed as 07 in the filename, even if it is 17 so I would like the first 0 to be changed to 1.

How can I do this using awk or sed?

I'm quite new to awk and sed, an programming in general. Have tried to search for a solution and instruction, but haven't manage to figure out how to solve this.

Can anyone help me?

Thanks. :)

torob
  • 3
  • 2
  • 1
    Possible duplicate of [Using sed to mass rename files](https://stackoverflow.com/questions/2372719/using-sed-to-mass-rename-files) – SuperKogito Apr 27 '19 at 18:43
  • Welcome to SO. Stack Overflow is a question and answer page for professional and enthusiastic programmers. Add your own code to your question. You are expected to show at least the amount of research you have put into solving this question yourself. – Cyrus Apr 27 '19 at 18:46

3 Answers3

0

Take your example:

awk -F'[_.]' '{$0=$1$2;sub(/^./,"1");sub(/..$/,".&")}1'<<<"071212_090537.jpg"

will output:

1712120905.37

If you want the file to be removed, you can let awk generate the mv origin new command, and pipe the output to |sh, like: (comments inline)

listYourFiles|    # list your files as input to awk

       awk -F'[_.]' '{o=$0;$0=$1$2;sub(/^./,"1");sub(/..$/,".&");
                      printf "mv %s %s\n",o,$0 }1' #this will print "mv ori new"

             |sh     # this will execute the mv command
Kent
  • 189,393
  • 32
  • 233
  • 301
  • Thanks a lot. This helped me getting on the right track. I ended up using the following code for my shell script: datetime=$(basename "$filename" .jpg | awk -F'[_]' '{$0=$1$2;sub(/^./,"1");sub(/..$/,".&"); print}') – torob Apr 27 '19 at 19:22
  • @Kent, see, this is why we don't just throw cryptic one-liners at noobs. Now he's spawning two pipes and a proc for *every file*. – vintnes Apr 27 '19 at 19:38
  • That `mv` is generating unquoted text so what you wanted to be file names is open to the shell for interpretation/globbing/wildcard expansion. It should be `printf "mv -- \047%s\047 \047%s\047\n",o.$0`/ – Ed Morton Apr 27 '19 at 20:50
  • I would change this `sub(/^./,"1")` to `sub(/^0/,"1")` just to avoid the dangers of `.` in regex – JBone Apr 27 '19 at 23:24
0

It's completely unnecessary to call awk or sed for this, you can do it in your shell. e.g. with bash:

$ f='071212_090537.jpg'
$ [[ $f =~ ^.(.*)_(.*)(..)\.[^.]+$ ]]
$ echo "1${BASH_REMATCH[1]}${BASH_REMATCH[2]}.${BASH_REMATCH[3]}"
1712120905.37

This is probably what you're trying to do:

for old in *.jpg; do
    [[ $old =~ ^.(.*)_(.*)(..)\.[^.]+$ ]] || { printf 'Warning, unexpected old file name format "%s"\n' "$old" >&2; continue; }
    new="1${BASH_REMATCH[1]}${BASH_REMATCH[2]}.${BASH_REMATCH[3]}"
    [[ -f "$new" ]] && { printf 'Warning, new file name "%s" generated from "%s" already exists, skipping.\n' "$new" "$old" >&2; continue; }
    mv -- "$old" "$new"
done

You need that test for new already existing since an old of 071212_090537.jpg or 171212_090537.jpg (or various other values) would create the same new of 1712120905.37

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
0

I think sed really is the easiest solution:

You could do this:

▶ for f in *.jpg ; do
  new_f=$(sed -E 's/([0-9]{6})_([0-9]{4})([0-9]{2})\.jpg/\1\2.\3.jpg/' <<< $f)
  mv $f $new_f
done

For more info:

  • You probably need to read an introductory tutorial on regular expressions.

  • Note that the -E option to sed allows use of extended regular expressions, allowing a more readable and convenient expression here.

  • Use of <<< is a Bashism known as a "here-string". If you are using a shell that doesn't support that, A <<< $b can be rewritten as echo $b | A.

Testing:

▶ touch 071212_090538.jpg 071212_090539.jpg                                                                                                                                                           
▶ ls -1 *.jpg
071212_090538.jpg
071212_090539.jpg
▶ for f in *.jpg ; do
  new_f=$(sed -E 's/([0-9]{6})_([0-9]{4})([0-9]{2})\.jpg/\1\2.\3.jpg/' <<< $f)
  mv $f $new_f
done
▶ ls -1
0712120905.38.jpg
0712120905.39.jpg
Alex Harvey
  • 14,494
  • 5
  • 61
  • 97