1

Pretty new to shell script, want to write script which checks if any file .300 extension exists on /exports/files on server 10.xx.xx.xx. If *.300 exists, move file to /exports/files/arch and send an email to support@abc.com. If *.300 isn't found then do nothing.

I tried below suggestion:

#! /bin/bash

    for FILE in `ls /exports/files/*.300`
    do
       mv $FILE /exports/files/arch
       echo "$FILE moved" | mailx -s $FILE moved support@abc.com 
    done

When there is no files its erroring out saying ls: cannot access /exports/files/*.300: No such file or directory. Is there any way to suppress this...

  • 1
    This really sounds an awful lot like a homework problem... – John May 28 '15 at 16:49
  • @john all things are difficult before they are easy, a i said i am new to scripting,I am still learning.Thanks for your comment though – Zaira banu May 28 '15 at 16:58
  • 1
    I didn't say anything about difficulty. I said it sounds like it was assigned as a homework problem. – John May 28 '15 at 17:00
  • Tell me if you mount the 10.*** server export on your pc – elbarna May 28 '15 at 18:04
  • @elbarna so far i got this and still working on it.I am running this on 10.xx.xx.xx server #!/bin/bash if ls /home/export/files/.300* 1> /dev/null 2>&1; then mv .300* /home/export/files/archive echo ".300 extenstion found and moved" | mailx -s "file found and moved" support@abc.com fi nothing happens – Zaira banu May 28 '15 at 19:04
2

[UPDATE]

#!/usr/bin/env bash
shopt -s nullglob #to make `("$src_dir"*.300)` works
src_dir="/exports/files/" #don't forget trailing slash /
dest_dir="/exports/files/arch/" #don't forget trailing slash /
err_f="/tmp/error.txt"
mv_f="/tmp/moved.log" #record moved file in case network down
email="support@abc.com"
touch "$err_f" #bcoz we use >> apppend
touch "$mv_f" #bcoz we use tee -a append
if [ ! -d "$src_dir" ]; then echo|mailx -s "Error: directory $src_dir not exist" "$email" 2>>"$err_f"; exit 1; fi
if [ ! -d "$dest_dir" ]; then echo|mailx -s "Error: directory $dest_dir not exist" "$email" 2>>"$err_f"; exit 1; fi
{
f=("$src_dir"*.300)
for ((i=0; i < ${#f[@]}; i+=1)); do
        mv -f "${f[i]}" "$dest_dir"  2>>"$err_f"; #-f do not prompt
        if [ $? -eq 0 ]; then
                if [ "$i" -eq 0 ]; then echo "$(date +"%Y-%m-%d %H:%M:%S")"; echo "The following files has been moved from $src_dir to $dest_dir"; echo; fi
                echo "$((i+1))." "$(basename "${f[i]}")" 'moved'; echo;
        else
                 echo| mailx -s "Error:  $(<"$err_f")" "$email" 2>>"$err_f"; break
        fi
done
} | tee -a "$mv_f" | mailx -E -s "The following files has been moved" "$email" 2>>"$err_f"

Example mail inbox screeshoot:

Received mail when mv error: enter image description here

Received mail when mv success: enter image description here

/tmp/moved.log to log files moved and /tmp/error.txt to log all erros, both files used to keep log even network down: enter image description here

Note:

  1. You shouldn't parse the output ofls
  2. mailx -E to avoid empty body, so it wouldn't sent if no file moved
  3. mailx only one if mv encounter error, by using break to break early instead of exit 1 because we still want to know which file has been moved before error occur.
  4. Advantage of cmd; if [ $? -eq 0 ] compare to implicitly if cmd is you can easily modify it to some other command which might require different return code.
  5. You should manually remove both /tmp/error.txt and /tmp/moved.log which will append from time to time.

Reference:

  1. http://mywiki.wooledge.org/ParsingLs
  2. http://lcorg.blogspot.com/2009/04/tip-redirecting-multiple-command.html
  3. https://serverfault.com/questions/349989/sending-mail-from-command-line-if-body-not-empty

  4. https://stackoverflow.com/questions/16036763/get-formatted-date-from-timestamp-with-rounded-milliseconds-bash-shell-script

  • works well but it sends individual email of each file.Is there a way i can send all file names in one mail? – Zaira banu May 29 '15 at 14:23
  • @Zairabanu Actually i have no idea what's your real requirement. 1. What if arch directory does not exist ? Then all the *.500 will rename to arch single file. 2. "is it possible to send 1 email with all file in it? " You can compress your directory and then attach to you email. – 林果皞 May 29 '15 at 19:37
  • both directory exist ,if .300 extension file exist in /exports/files then it should be moved to /exports/files/arch.If .300 file doesnot exist then it shouldnot do anything. all files moved i want in single email . – Zaira banu May 29 '15 at 19:41
  • both the directory exists , if .300 extension file exist in /exports/files then it should be moved to /exports/files/arch.If .300 file doesnot exist then it shouldnot do anything. And if the file exists and is moved, then should receive email with details(name of the file) of file ? – Zaira banu May 29 '15 at 19:47
  • 1
    appreciate your time and thank you for your help.may success follow you :) good luck :) – Zaira banu May 31 '15 at 3:41
2

Some thing like this should do the trick. If you need to remote in to the server use ssh certificates and executes this script using ssh.

    #! /bin/bash

    for FILE in `ls /exports/files/*.300`
    do
       mv $FILE /exports/files/arch
       echo "$FILE moved" | mailx -s $FILE moved support@abc.com 
    done
  • if there are multiple files with .300 extension , will this send multiple emails...and also its returning error if the file is not found , is there any way to suppress the error – Zaira banu May 28 '15 at 19:28
  • if there are multiple files with .300 extension , will this send multiple emails..?.and also its returning error if the file is not found and alos sends email even though the file is not found or moved , is there any way to suppress the error – Zaira banu May 28 '15 at 20:03
0

just for fun

 #! /bin/bash

ls /exports/files/*.300 | while read FILE 
do
   if mv $FILE /exports/files/arch
   then echo "$FILE moved" 
fi
done | mailx -s files moved support@abc.com 

will give you a single mail with all moved file, and skipping the error.

with just 3 level of pipes.

Edit:

with few files :

#! /bin/bash
if ls /exports/files/*.300 > /dev/null 2>&1
then 

   ls /exports/files/*.300 | awk '{printf "%s moved\n",$0 }' | mailx -s files moved support@abc.com
   mv /exports/files/*.300 /exports/files/arch

 else 
   echo no .300 file found | mailx -s no .300 files moved support@abc.com

fi

in case of arg list too long

#! /bin/bash
if ls /exports/files/*.300 > /dev/null 2>&1
then 
   ls /exports/files/*.300 | while read FILE 
   do
      if mv $FILE /exports/files/arch
      then echo "$FILE moved" 
      fi
   done | mailx -s files moved support@abc.com 
fi
  • when i run this script "ls"errors out ...No such file or directory Null message body; hope that's ok --->thats the message i get – Zaira banu May 29 '15 at 14:25
  • @Zairabanu: His script should work. You'll need to do some debugging to figure out why it breaks. Try removing the | mailx... command and see what your output looks like. There is no way to go into the then clause unless ls finds something in the beginning. You can also do this after the then: (all on one line) ls /exports/files/*.300; exit and see what it prints. Your error is very odd. – Mike S May 29 '15 at 14:59
  • @MikeS on the top most script, in case of no foo.300 files, ls loop is empty, thus generating a mail with no body. – Archemar May 29 '15 at 15:11
  • @Archemar above script worked,i removed word " moved" from echo line as its keep on repating like file1 moved, file2 moved.Is there a way we can add a date before(above) "$FILE moved" – Zaira banu May 29 '15 at 15:19
  • @Archemar above script worked,i removed word " moved" from echo line as its keep on repating like file1 moved, file2 moved.Is there a way we can add a date before(above) "$FILE moved" – Zaira banu May 29 '15 at 19:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.