3

I am trying to prefix timestamp and add an extension to files using a script. I have file ABC which I is being renamed to ABC.txt

DIRECTORY=`find /path/to/file -type f ! -name "*.*"`
NOW=$(date +%Y-%m-%d-%H%M%S)

for file in $DIRECTORY; do

    mv "$file" "$file"_"${NOW}.txt"
    done

The output above works but as a suffix, if I switch it around

    mv "$file" "${NOW}"$file".txt"

I'm getting cannot mv: cannot move`2019-10-18-231254/path/to/file/ABC.txt': No such file or directory

I can see the issue is with the $Directory as this is calling the full path when doing the mv. Could someone please help simplify this?

Samosa
  • 81
  • 1
    You can get the filename from a path like this: https://stackoverflow.com/a/965072/2519977. This may be a duplicate. The problem is that $file contains the whole path and not just the filename. If everything is happening in the same folder, the filename should suffice - if not you'd also have to extract the path. Or maybe sed could help as well... – rudib Oct 18 '19 at 22:37

2 Answers2

3

I'd suggest avoiding the loop over the find command's output for the reasons discussed here:

Instead, consider using -execdir, with a shell one-liner to remove the path components:

#!/bin/bash

export NOW=$(date +%Y-%m-%d-%H%M%S)

find /path/to/file -type f ! -name '*.*' -execdir sh -c '
  for f; do echo mv "$f" "${NOW}_${f#./}"; done
' find-sh {} +

Remove the echo once you are happy that it is doing the right thing. Note that NOW needs to be exported so that its value is available in the sh -c subshell.

If your find implementation doesn't provide -execdir, then you can use -exec if you remove and replace the path explicitly:

find /path/to/file -type f ! -name '*.*' -exec sh -c '
  p="${1%/*}"; echo mv "$1" "$p/${NOW}_${1##*/}"
' find-sh {} \;
steeldriver
  • 81,074
  • Great thanks for the help, It's prefixing as i required. – Samosa Oct 18 '19 at 23:14
  • thank, it help me. In my case, my need is just to add timestamp prefix to archive files: horodate_prefix=$(date +%Y%m%d_%HH%M)
    export file_name=${horodate_prefix}_save.tar.gz
    echo $file_name
    # create tar
    tar zcvf $file_name *.ext
    – bcag2 Jan 22 '20 at 09:42
1

Using GNU Parallel:

find /path/to/file -type f ! -name "*.*" -print0 |
  parallel -0 mv {} {//}/$(date +%Y-%m-%d-%H%M%S)_{/}.txt

Please consider using ISO8601 for timestamps:

find /path/to/file -type f ! -name "*.*" -print0 |
  parallel -0 mv {} {//}/$(date +%Y-%m-%dT%H:%M:%S)_{/}.txt

Or:

find /path/to/file -type f ! -name "*.*" -print0 |
  parallel -0 mv {} {//}/$(date +%Y%m%dT%H%M%S)_{/}.txt

That means you can use a standardized ISO8601 parser for parsing the timestamp later.

Ole Tange
  • 35,514