Find the answer to your Linux question:
Results 1 to 5 of 5
Hi all, I'm writing a script to preserve the creation dates of the files to be converted to other formats. For the names of the converted files, I believe these ...
  1. #1
    Linux User
    Join Date
    May 2008
    Location
    NYC, moved from KS & MO
    Posts
    251

    problem with passing argument to -exec in find command

    Hi all, I'm writing a script to preserve the creation dates of the files to be converted to other formats. For the names of the converted files, I believe these are the most common patterns, for example,
    • *.doc -> *.txt

    • *.doc - > *.doc.txt

    and I came up with this bash script
    Code:
    #!/bin/bash
    # script name: fixdate
    usage() {
      echo "usage: `basename $0` src_path src_ext dest_path dest_ext [append|replace]"
    }
    MODE="replace"
    
    case $# in
      5|4)
        [ $# -eq 5 ] && MODE=$5
        case $MODE in
          append)
            find $1 -name "*.$2" -exec touch -c -r {} $3/`basename {}`.$4 \;
            ;;
          replace)
            find $1 -name "*.$2" -exec touch -c -r {} $3/`basename {} $2`$4 \;
            ;;
          *)
            usage
            ;;
        esac
        ;;
      *)
        usage
        ;;
    esac
    It works only in the append mode. For example, if I do a
    Code:
    fixdate . doc . txt append
    , it works as expected, that is, creation dates of ./*.txt got replaced with those of ./*.txt.doc
    But when I try to run
    Code:
    fixdate . doc . txt replace
    , or
    Code:
    fixdate . doc . txt
    , the creation dates of ./*.txt don't get replaced by those of ./*.doc
    I can work around this by changing the bold line in the script into
    Code:
     find $1 -name "*.$2" | while read F; do touch -c -r $F $3/`basename $F $2`$4; done
    I kind of know that $2 in the original code didn't get passed into `basename` in -exec under replace mode but I don't know exactly why and I hope someone could point out what the problem is. Thank you.

  2. #2
    Linux Newbie
    Join Date
    Jul 2008
    Posts
    181
    Shouldn't that be

    Code:
    find $1 -name "*.$2" -exec touch -c -r {} $3/`basename {}`$2 $4 \;

  3. #3
    Linux User
    Join Date
    May 2008
    Location
    NYC, moved from KS & MO
    Posts
    251
    Quote Originally Posted by burschik View Post
    Shouldn't that be

    Code:
    find $1 -name "*.$2" -exec touch -c -r {} $3/`basename {}`$2 $4 \;
    No it doesn't work this way.

  4. #4
    Linux Newbie
    Join Date
    Jul 2008
    Posts
    181
    Right. I'm afraid that won't work, as the "{}" has not yet been replaced by the filename found when you call basename. It might be a better idea to generate a list of matching filenames and then feed it to touch via a loop, e.g.

    Code:
    find -name whatever | while read filename;
        do manipulate filename;
        touch -cr oldname newname; 
    done

  5. #5
    Linux User
    Join Date
    May 2008
    Location
    NYC, moved from KS & MO
    Posts
    251
    My final version of this script:
    Code:
    #!/bin/bash
    # script to change converted files' creation dates
    # usage:
    #   fixdate src_path src_ext dest_path dest_ext [append|replace]
    usage() {
      echo "usage:"
      echo "        `basename $0` src_path src_ext dest_path dest_ext [append|replace]"
      echo "        by default, replace mode will be used, that is, for example, converted files are in *.txt format while the origins are *.doc format"
      echo "        alternatively, append mode can be specified if the converted files are in *.doc.txt format"
      echo "example:"
      echo "        `basename $0` . doc converted/ txt"
      echo "        set the dates of *.txt under converted/ to be the same as those of ./*.doc"
      echo "note:"
      echo "        filenames/paths in this script are case sensitive"
    }
    
    MODE="replace"
    
    case $# in
      5|4)
        [ $# -eq 5 ] && MODE=$5
        case $MODE in
          append)
            find $1 -name "*.$2" -type f | while read F; do dest_name=$3/`basename "$F"`.$4; touch -c -r "$F" "${dest_name}"; done
            ;;
          replace)
            find $1 -name "*.$2" -type f | while read F; do dest_name=$3/`basename "$F" $2`$4; touch -c -r "$F" "${dest_name}"; done
            ;;
          *)
            usage
            ;;
        esac
        ;;
      *)
        usage
        ;;
    esac
    This improved version takes care of the argument passing problem, also the modifications apply to only files, whose names might contain space(s).

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...