1

I've seen a useful command like this:

for f in *; do t=$(echo $f | sed -E 's/[-. mov]//g'); touch -t $t "$f"; done

What do I need to change in that command, in order to keep only the "time stamp" string for a file with the following naming convention?

aaaa@XXXXXX(XXXXXXX)_20170201101315.mp3
2
  • What type of characters are actually in aaaa@XXXXXX(XXXXXXX), other then @, ( and ) are a... and X... alpha characters only or alphanumeric characters? Additionally, I saw your now deleted question you wrongfully posted as a answer to another question and are you wanting to do the same thing, that is, touch the files to change the date-time stamp? (Just want to be sure that's what you're wanting.) Feb 3, 2017 at 18:16
  • Yer sir, it's me... the sample of the file name is - Chiama@800031141(800031141)_20160725093945.mp3 and I'd like to run a script to put the data stamp value described into the file name into the "TOUCH" parameter to change the creation and modification date with that data. Of Course the date number in the name of the file should be correct except the seconds witch are not necessary into the TOUCH parameter. Feb 3, 2017 at 19:01

2 Answers 2

0

I'd take a little different approach, in that I'd want to test that the filename ends in .mp3 and the length of the t variable is 12 characters long before processing. This should keel it from acting on files that do not conform to the pattern and avoid throwing errors, even though the errors in this case should be non-fatal. I just don't like unnecessary junk outputted.

This is an example of it in script form:

#!/bin/bash

for f in *.mp3; do
    t="$(awk '/_.*/ { match($0, /_.*/); print substr($0, RSTART + 1, RLENGTH - 7); }'<<<"$f")"
        if [[ ${#t} -eq 12 ]]; then
            touch -t "$t" "$f"
        fi
done

This is an example of the script as a one-liner, albeit a long one.

for f in *.mp3; do t="$(awk '/_.*/ { match($0, /_.*/); print substr($0, RSTART + 1, RLENGTH - 7); }'<<<"$f")"; if [[ ${#t} -eq 12 ]]; then touch -t "$t" "$f"; fi; done

Which can be shortened to:

for f in *.mp3; do t="$(awk '/_.*/ { match($0, /_.*/); print substr($0, RSTART + 1, RLENGTH - 7); }'<<<"$f")"; [[ ${#t} -eq 12 ]] && touch -t "$t" "$f"; done

If you really want to shorten it further:

for f in *; do t="$(awk '/_.*/ { match($0, /_.*/); print substr($0, RSTART + 1, RLENGTH - 7); }'<<<"$f")"; touch -t "$t" "$f" 2>/dev/null; done

The above form of the compound command does no error checking and redirects the error output of the touch command so it doesn't clutter the screen. This form is fine in this use case as a malformed touch commands will be non-fatal.

1
  • It woks perfectly, I've run the script and in few minutes I've recovered over a thousand of files's time stamp. Very impressive, thank you so much Feb 3, 2017 at 22:09
1

You can practice on the command line to get a working sed script:

$ echo "aaaa@XXXXXX(XXXXXXX)_20170201101315.mp3" | sed -e "s/^.*_//g" -e "s/\.mp3$//g"
20170201101315

Since the timestamp in your filename includes the seconds and it's not in a format that touch accepts (it wants a '.' before the seconds), I exclude them with a cut:

for f in *; do t=$(echo $f |  sed -e "s/^.*_//g" -e "s/\.mp3$//g" | cut -c -12); echo touch -t $t "$f"; touch -t $t "$f"; done
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .