Find the answer to your Linux question:
Results 1 to 7 of 7
I have very little linux experience. And need some help with a bash script. I need to a script I can set cron to run to sort files out of ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Mar 2010
    Posts
    3

    [SOLVED] Bash Script; Sort files into directory based on data in the file name


    I have very little linux experience. And need some help with a bash script. I need to a script I can set cron to run to sort files out of a holding folder into final folders.

    It doesn't necessarily have to be bash, but I think it would be sufficient for this.

    File names are formatted as such when created: Dest-Date-Time-CID-Destination#

    I want the files to be moved from a all in one holding folder to a folder structure like this.

    .../storage/year/month/day/Destination#/VarX(type)/hour/CID/'File'

    I would need an if/else if/else statement to say if Dest = A set VarX = B

    If for example the file name was
    infinity-20100927-17:00-1112223333-4445556666.wav

    I would like the above file to end up moved from

    .../holding

    to

    .../storage/2010/09/27/4445556666/Inbound/17/1112223333/infinity-20100927-17:00-1112223333-4445556666.wav

    So the script will need to make directories based on information in the file name which is delimited by single dashes. Then move files from the holding folder to the newly created "sorted" folders.

    Thank You for your time and help.

  2. #2
    Linux User Manko10's Avatar
    Join Date
    Sep 2010
    Posts
    250
    I think a script with ls, grep and sed in a for loop should do the job pretty well.

  3. #3
    Just Joined!
    Join Date
    Sep 2007
    Posts
    19

    awk maybe

    Try something like:

    ls -1 | gawk -F"-" '{
    if (something = other-thing )
    do nonsense;
    system("mv " $0 " <Fixed part of path>/" sub($2,1,4)"/"..."/"$5 etc)
    }'

  4. $spacer_open
    $spacer_close
  5. #4
    Just Joined!
    Join Date
    Mar 2007
    Posts
    5
    Something like this should do it:-

    Code:
    #!/bin/bash
    
    # Set these two variables to the full pathname
    # of your holding and storage directories
    
    holding=/tmp/MTAS/holding
    storage=/tmp/MTAS/storage
    
    cd $holding
    
    for file in $(ls -A)
    do
      echo $file
      Dest=$(echo $file | cut -d'-' -f 1)
      Date=$(echo $file | cut -d'-' -f 2)
      Time=$(echo $file | cut -d'-' -f 3)
      CID=$(echo $file | cut -d'-' -f 4)
      Destination=$(echo $file | cut -d'-' -f 5 | cut -d'.' -f 1)
    
      year=${Date:0:4}
      month=${Date:4:2}
      day=${Date:6:2}
    
      hour=${Time:0:2}
    
      storage_dir=$storage/$year/$month/$day/$Destination/Inbound/$hour/$CID
    
      # Remove the -v for no confirmation of directory creation
    
      if [ ! -d $storage_dir ]
      then
        mkdir -v -p $storage_dir
      fi
    
      # Remove the -v for no confirmation of file movement
    
      mv -v $file $storage_dir
    done
    You could add more validation tests I suppose but this works for the case you give in your example. Also - is the 'Inbound' part of your storage directory always a constant?

  6. #5
    Linux Enthusiast
    Join Date
    Jan 2005
    Location
    Saint Paul, MN
    Posts
    661

    How about only in bash... no sed, grep, cut, etc ...

    Assuming the file name is the variable, name, look at this example...

    Code:
    ext="${name##*\.}"
    parts=( $( IFS='-' && echo ${name%\.${ext}} ) )
    the_date="${parts[1]}"
    dest="${parts[0]}"
    year="${the_date:0:4}"
    month="${the_date:4:2}"
    day="${the_date:6:2}"
    time="${parts[2]}"
    cid="${parts[3]}"
    destination="${parts[4]}"
    mv .../holding/${name}  .../storage/${year}/${month}/${day}/${time}/Inbound/${time:0:2}/${cid}/${name}
    show testing example:

    Code:
    function testing
    {
        name="$1"
    
        ext="${name##*\.}"
        parts=( $( IFS='-' && echo ${name%\.${ext}} ) )
        the_date="${parts[1]}"
        dest="${parts[0]}"
        year="${the_date:0:4}"
        month="${the_date:4:2}"
        day="${the_date:6:2}"
        time="${parts[2]}"
        cid="${parts[3]}"
        destination="${parts[4]}"
        echo mv .../holding/${name}  .../storage/${year}/${month}/${day}/${time}/Inbound/${time:0:2}/${cid}/${name}
    }
    
    testing infinity-20100927-17:00-1112223333-4445556666.wav
    which produces the output:

    Code:
    mv .../holding/infinity-20100927-17:00-1112223333-4445556666.wav .../storage/2010/09/27/17:00/Inbound/17/1112223333/infinity-20100927-17:00-1112223333-4445556666.wav
    Last edited by alf55; 09-30-2010 at 04:09 AM. Reason: Changed function to pass in the name as argument 1

  7. #6
    Just Joined!
    Join Date
    Mar 2010
    Posts
    3
    Code:
    #!/bin/bash
    for file in $(ls)
    do set $(echo $file | awk -F- '{print $1, $2, $3, $4, $5}')
       filestart=$1
       fullyear=$2
       fulltime=$3
       aftertimesub=$4
       suffix=$5
       year=$(echo $fullyear |cut -c1-4)
       month=$(echo $fullyear |cut -c5-6)
       day=$(echo $fullyear |cut -c7-8)
       hour=$(echo $fulltime |awk -F: '{print $1}')
       suffixsubdir=$(echo $suffix |awk -F\. '{print $1}')
       if [ $1 == "infinity" ]; then
       typeX="Inbound"
       	else 
       if [ $1 == "bellout" ]; then
    	typeX=Outbound
         else
       if [ $1 == "sipout" ]; then
    	typeX=Outbound 
         else
       if [ $1 == "PersonalLine" ]; then
    	typeX=Inbound
         else
    	typeX=Unknown
       fi
       fi
       fi
       fi
       type=$typeX
       newdir=$(echo /etc/test/Store/$year/$month/$day/$suffixsubdir/$type/$hour/)
       if ! [ -d $newdir ]
       then echo Directory $newdir does not exist.  Creating same.
            mkdir -p $newdir
       fi
       mv $file $newdir
    done
    Asked on another forum and got some quicker responses yesterday. This is my "finished" script I'm actively using now. but it isn't fine tuned yet for instance going to replace

    example changing to

    for file in * instead of for file in $(ls)

    and moving to using case instead of nested Ifs

    but Thank You for the help anyway

  8. #7
    Just Joined!
    Join Date
    Mar 2010
    Posts
    3
    Final Code

    Code:
    #!/bin/bash
    for file in *.wav *.mp3 ; do
     set $(echo $file | awk -F- '{print $1, $2, $3, $4, $5}')
       filestart=$1
       fullyear=$2
       fulltime=$3
       aftertimesub=$4
       suffix=$5
       year=$(echo $fullyear |cut -c1-4)
       month=$(echo $fullyear |cut -c5-6)
       day=$(echo $fullyear |cut -c7-8)
       hour=$(echo $fulltime |awk -F: '{print $1}')
       suffixsubdir=$(echo $suffix |awk -F\. '{print $1}')
    case $filestart in
        "infinity")type=Inbound;;
        "bellout")type=Outbound;;
        "sipout")type=Outbound;;
        "PersonalLine")type=Inbound;;
        "mili")type=Outbound;;
        *)type=Unknown;;
    esac
       newdir=$(echo /var/Store/$year/$month/$day/$type/$suffixsubdir/$hour/)
       if ! [ -d $newdir ]
       then echo Directory $newdir does not exist.  Creating same.
            mkdir -p $newdir
       fi
       mv $file $newdir
    done

Posting Permissions

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