3

I have a directory that contains the backup of many computers using NTFS file system.

/backup/REP1/database
/backup/REP2/database

I now want to scp from the backup file server to the database server, both are running Ubuntu 14.

Inside the backup directories are Visual FoxPro files that are not all the same case, but are the same name. There are other files in the backup directory that I do not want to scp.

/backup/REP1/database/usersupport.DBF
/backup/REP1/database/System.dbf

/backup/REP2/database/UserSupport.dbf
/backup/REP2/database/system.dbf

In my bash script I am using 2 loops to create the remote path and file names.

computer_list=(REP1 REP2 REP3 REP4 REP5 REP6 REP7 REP8 REP9 REP10 REP11 REP12 REP13 REP14 REP15 REP16)
file_list=(usersupport.cdx usersupport.dbf usersupport.fpt system.dbf)

  for computer_name in ${computer_list[@]}; do
        ## delete working dir
        delete_working_dir
        for file_name in ${file_list[@]}; do
            remote_file=${remote_path}${computer_name}/${dow}/CustomerData/system/${file_name}
            local_file=${working_directory}${file_name}
            #echo $remote_file
            echo $local_file
            # scp -i $ID $USER@$HOST:$remote_file $local_file > /dev/null 2>&1
            scp -i $ID $USER@$HOST:$remote_file $local_file
            # change databse file permissions
            chmod 0777 ${local_file}
        done
        # process mysql
        process_mysql
        ## delete working dir
        delete_working_dir

done

The command scp will not copy the source file if the case is not the same.

What would be the correct or easiest way to get the source file regardless of case.

I did try shopt -s nocasematch, but no go.

Can I use substitution on the remote file name? [:lower]

This user uses this scp -B -p ${Auser}@${aSrcHOST}:${aSrcDIR}/*.[Oo][Kk] $aTgtDIR So I believe the substitution might work. I am not sure of the syntax.

  • your file_list says "... system.dbf" but you'd like it to scp not only "system.dbf" but also "System.dbf" ? – Jeff Schaller Sep 14 '16 at 18:23
  • and how many variations of case can there be? UsErSuPpOrT.dBf? – Jeff Schaller Sep 14 '16 at 18:25
  • Exactly, the files originated on a NTFS file-system so the case could be anything. usersupport.DBF; UserSupport.dbf... – jc__ Sep 14 '16 at 18:27
  • globbing would help grab the remote filename(s) but you're also specifying the local filename; would you be OK with a variation that told scp to grab/glob multiple files, and gave it a destination directory instead of a single filename? – Jeff Schaller Sep 14 '16 at 19:42
  • as a work around, yes. There are other files in the source directory that i really dont want to copy because some are several hundred MB in size, but I can. I would then need to rename the local files all lower case for the rest of the script. – jc__ Sep 14 '16 at 19:46
2

Here's how I would approach it:

  1. Create a function that generates globs for filenames based on the requirement (any character could show up as upper- or lower-case).

  2. Modify the loop to have scp use the glob as the remote filename, and the already lower-cased filename as the local filename.

This will create the same one scp connection per file, per computer as you do currently, but the globbing will pick up the remote file, no matter how it is "cased".

Here's the (bash-specific) function:

function ul {
  # for each character in $1, convert it to upper and lower case, then
  # enclose it in [ ]
  out=
  for (( i=0; i< ${#1}; i++ ))
  do
    c=${1:$i:1}
    if [[ "$c" =~ ^[[:alpha:]]$ ]]
    then
      uc=${c^}
      lc=${c,}
      out="${out}[${uc}${lc}]"
    else
      out="${out}${c}"
    fi
  done
  printf "%s" "$out"
}

So you put that into the same script, or in some common area that gets sourced.

To demonstrate its usage:

$ g=$(ul system.dbf)
$ echo "$g"
[Ss][Yy][Ss][Tt][Ee][Mm].[Dd][Bb][Ff]

For step 2, this is how I modified your inner loop:

    for file_name in ${file_list[@]}; do
        g=$(ul "$file_name")
        remote_file=${remote_path}${computer_name}/${dow}/CustomerData/system/${g}
        local_file=${working_directory}${file_name}
        echo $local_file
        scp -i $ID $USER@$HOST:$remote_file $local_file
        chmod 0777 ${local_file}
    done

I added the g= assignment as well as the remote_file assignment (at the end of the line).

  • This works great. In effect this will add the substitution characters to each letter in the file name. system.dbf becomes [Ss][Yy][Ss][Tt][Ee][Mm].[Dd][Bb][Ff]. I now know that I can glob the source file in scp without getting a list of files first. Thank you again. – jc__ Sep 15 '16 at 13:51

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.