Question

I have a script, named bundle, which uses Here-documents to combine text files into a single file. The files, whose names are passed as arguments when calling the bundle script, are placed within a single file (here named filebundle) which can then be executed as a bash script to unbundle the files back into separate files.

Here is the bundle script:

#! /bin/bash
# bundle: group files into distribution package.

echo "# To unbundle, bash this file."

for i
do 
    echo "echo $i 1>&2"
    echo "cat >$i <<'End of $i'"
    cat $i
    echo "End of $i"
done

This, when executed as follows

$ bash bundle file1.txt file2.txt > filebundle

results in the following file, named filebundle:

# To unbundle, bash this file.
echo file1.txt 1>&2
cat >file1.txt <<'End of file1.txt'
This is file1.
End of file1.txt
echo file2.txt 1>&2
cat >file2.txt <<'End of file2.txt'
This is file2.
End of file2.txt

which, as I said, can be bashed to unbundle both file1.txt and file2.txt

My question is the following: I have to rewrite the bundle script so that the filebundle file that results from it can be executed with or without filenames as arguments and can unbundle the files contained in it accordingly.

For example:

$ bash filebundle file2.txt

would unbundle only file2.txt and not file1.txt. Additionally, bashing filebundle without arguments would unbundle all files within filebundle.

I assume I should use a "if...then...else" control structure to unbundle files according to the arguments passed, and I can only think of using something like

for i in $@; do
    grep "$i" <<'End of $i' | bash
done

to find specific files within filebundle and unbundle them. Yet I can't quite seem to put these together into something that works.

Your thoughts and advice are greatly appreciated.

Was it helpful?

Solution

You don't have to find specific files when you unbundle. The if..then takes care of that.

Make the file bundle be a set of blocks like this:

if [[ $# = 0 ]] || contains "file1.txt" "$@"
then
cat > file1.txt  << 'End of file1.txt'
DATA HERE
End of file1.txt
fi

where contains is a function that checks for the first element amongst the rest, e.g.

contains() { 
    var=$1
    shift
    for f
    do 
        [[ $var = "$f" ]] && return 0
    done
    return 1
}

Each file will then only be unbundled if either there are no arguments, or if the filename is amongst them.

You can add additional logic in the header to ensure all the filenames specified exist in the file before you start running these blocks.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top