revision of copy script to allow for single quote

I have the following script that I use to copy a list of files from one dir to another,

#!/usr/bin/bash
# $1=filename of file with the list of files to copy
# $2=column header for col in list file with filenames (filePath in most cases)
# $3=src dir
# $3=destination dir

FILE_LIST="$1"
FILE_FIELD="$2"
SOURCE_DIR="$3"
DEST_DIR="$4"

if [ $# -ne 4 ]
then
   echo "usage: $0 file_list field src_dir dest_dir" >&2
   exit 1
fi
if [ ! -f "$FILE_LIST" ]
then
    echo "Invalid filelist $FILE_LIST">&2
    exit 2
fi
# create destination directory if it doesnt' exist
if [ ! -d "$DEST_DIR" ]
then
    mkdir $DEST_DIR
fi
if [ ! -d "$SOURCE_DIR" ]
then
    echo "Invalid source directory">&2
    exit 4
fi
 
awk -vS="$SOURCE_DIR" -vFLD="$FILE_FIELD" 'NR==1{for(i=1;i<=NF;i++)if($i==FLD)w=i;next}
w {print S "/" $w}' $FILE_LIST | xargs  -r cp --target-directory="$DEST_DIR"

This reads the list of file names from a column in a text file and then copies those files from the src dir to the target dir.

I have run into a problem as some of my file names contain single quotes and I am getting an xargs error,

"xargs: unmatched single quote; by default quotes are special to xargs unless you use the -0 option"

I tried adding -0, but I got an error that the argument line was too long. I don't know xargs well enough to know exactly which arguments I need, or if I need to use a different approach to the script. The filenames will never have spaces or double quotes, but may have . , ' - _ ~ ( ) [ ] { } < >

I appreciate the assistance as there are often a lot of files and no good solution in the absence of a script.

LMHmedchem

try this:

awk -vS="$SOURCE_DIR" -vFLD="$FILE_FIELD" -v qq='"' 'NR==1{for(i=1;i<=NF;i++)if($i==FLD)w=i;next} w {print qq S "/" $w qq}' $FILE_LIST | xargs  -r cp --target-directory="$DEST_DIR"
1 Like

Thanks, I will give that a try. I made an error in my post in indicating that filenames may have<>, since those are not legal windows characters.

---------- Post updated at 01:30 PM ---------- Previous update was at 01:18 PM ----------

Also, the file names are not all bracked with single quotes, but just may contain a single quote here and there,

Such as,

N-ethyl-N'-ethylpropane-1,3-diamide.mol

LMHmedchem

Instead of xargs I would use pax -rw "$DEST_DIR" . pax is part of nearly every unix flavor out there. Linux is the only notable exception, where its presence isn't guaranteed. If your system has it, it should do nicely.

Regards,
Alister

1 Like

This is winXP running under cygwin. I did which pax and don't find anything. I will look and see if it is in the package manager.

LMHmedchem

Did you try vgersh99's suggestion? It should work if, as you said, there are no double quotes.

Another alternative would be to insert a backslash before every quote.

Regards,
Alister

I am in the middle of revising one of the lists. When I am done with that, I will test the modifications suggested by vgersh99. This is the sort of operation where OSs seem to fall very short in terms of providing reasonable tools. I don't know what I would do without scripts. Just try opening a folder in windows when it has 500,000 files in it, let alone trying to pick out a few thousand that you need. :wall:

---------- Post updated at 04:07 PM ---------- Previous update was at 02:44 PM ----------

I tried the suggestion of vgersh99 and it worked fine. I think I need to add stripping out of double quotes if they occur since excel tends to put those in when you save to a text file.

It would also be nice to have a similar script that would rm the file names on a list from a specified directory. I guess it makes sense to stick to the linux tool mentality of one tool per operations instead of trying to make a script that does two different things based on arguments.

LMHmedchem