Bash script: if any argument is “N” then function

2019-07-20 01:03发布

(I'll reuse this as it's about the same thing).
I have managed to make a usable script that does everything what's explained below the code block, except the order of the arguments, i.e.:

./test.sh B N A

will delete B.zip, create a new archive, but stops there, A will not be processed. It's fine, I can keep N as the last argument, no problem. Also, the echo "no backup needed, removing" does not work for some reason, but that's rather optional.

My question is: can what I have done be improved/altered somehow so that if there are other folders to be added in time the only changes to the script to be the DIRx entries? The biggest problem I see is modifying the block between <start> and <stop>. Here is the script:


#!/bin/bash

DIR1=A
DIR2=B
DIR3=C

bak()
{
    if [[ "$*" == N ]]
    then
        if [ $1 == N ]
        then
            :
        else
            echo "no backup needed, removing"
            rm -v $1.zip
        fi
    else
        if
            [ -f $1.zip ]
        then
            /bin/mv -vi $1.zip BKP/$1.zip_`/bin/date +"%H-%M"`
        else
            echo "no "$1".zip"
        fi
    fi
}

archive()
{
    if [ $* == N ]
    then
        :
    else
        if [ $1 == C ]
        then
            7z a -mx=9 $1.zip ../path/$1 -r -x\!$1/nope
        else
            7z a -mx=9 $1.zip $1 -r -x\!$1/bogus
        fi
    fi
}

########### <start> ####################
if [ -z "$*" ] || [[ "$#" -eq 1 && "$1" == N ]]
then
    bak "$DIR1"
    bak "$DIR2"
    bak "$DIR3"
    archive "$DIR1"
    archive "$DIR2"
    archive "$DIR3"
fi
############## <stop> #####################

#if [[ "$#" -eq 1 && "$1" == N ]]
#then
#   rm -v "$DIR1".zip
#   rm -v "$DIR2".zip
#   rm -v "$DIR3".zip
#   archive "$DIR1"
#   archive "$DIR2"
#   archive "$DIR3"
#fi

if [[ "$#" -gt 1 && "$*" == *N* ]]
then
    while [ "$#" -gt 1 ]
    do
        if [ "$1" == N ]
        then
            :
        else
            rm -v "$1".zip
        fi
        archive "$1"
        shift
    done
else
    while [ "$#" -ge 1 ]
    do
        bak "$1"
        archive "$1"
        shift
    done
fi
exit 0

Now, here's what I have and want it to do. The current directory holds the script, test.sh, and the folders A and B. ls -AR produces this:

A  B  test.sh

./A:
1.txt  2.txt  bogus

./B:
3.txt  4.txt  bogus

There is another folder, C, in ../path/. The same ls -AR ../path gives this:

../path:
C

../path/C:
5.txt  6.txt  nope

../path/C/nope:
q.doc  w.rtf

What I want the script to do. When run with no arguments:

./test.sh

1) checks for existing zip archives in the current directory
1.a) if they exist, a backup is made for each with additional date suffix into BKP/.
2.a) if not, it lets you know
2) the three folders, A, B and C are archived, folders A and B without A/bogus and B/bogus and folder C without ../path/C/nope/* and ../path/C/nope/ .

If run with arguments, these can be any of A, B or C, with an optional N. If run with N, only:

./test.sh N

then no archive check/backup will be performed, any archives already existent will be deleted and all 3 folders get archived. If run with any combination of A, B or C, for example:

./test.sh A C

then only archives A.zip and C.zip have a check and backup and only folders A and C are archived, A without A/bogus and C without ../path/C/nope/* and ../path/C/nope/ . If run with any combination of A, B or C, but with additional N, i.e.:

./test.sh B N C

Then no check/backup is performed for B.zip and C.zip, the archives (if existent) get deleted and the folders B and C are archived.

The archives will have (inside) the folder as the root directory (i.e. open up the archive and you'll see A, B or C first) and all three of them have exceptions to the list of files to be processed: A and B don't need bogus, while C doesn't need subfolder none and anything inside it. I use 7z instead of zip because I can write:

7z a x.zip ../path/./C/bla/bla

and have C as the root directory; I couldn't do it with zip (most likely I don't know how to, it doesn't matter as long as it works).

So far, the checking and the backup work. The archiving, if no exceptions are added and I remove the $PATH thing, work. The whole script doesn't. I would have posted every combination I have done so far, but 99% of them would have probably been impossible and the rest childish. I couldn't care less how it looks as long as it does the job.


Very optional: can an alias (or some sort) like "SCF" be made to "Supercalifragilistic"? The C folder has a rather long name (I could just make a symlink, I know). I have no idea about this one.

标签: linux bash shell
1条回答
你好瞎i
2楼-- · 2019-07-20 01:56

I managed to do it. It's probably very childish and the worst possible script but I don't care right now, it works. Of course, if somebody has a better alternative to share, it's welcome, until then here's the whole script:


#!/bin/bash
# ./test.sh     = 1. searches for existing archives
#               1.a. if they exist, it backups them into BKP/.
#               1.b. if not, displays a message
#             2. archives all the directories in the array list
# ./test.sh N       = 1. deletes all the folder's archives existent and
#           specified in the array list
#             2. archives all the directories in the array list
# ./test.sh {A..F}  = 1. searches for existing archives from arguments
#               1.a. if they exist, it backups them into BKP/.
#               1.b. if not, displays a message
#             2. archives all the directories passed as arguments
# ./test.sh {A..F} N    = 1. deletes all the archives matching $argument.zip
#             2. archives all the directories passed as arguments

# The directories to be backed-up/archived, all in the current (script's) path
# except "C", on a different path
DIR=(A B C D E F)

# The back-up function, if any argument is "N", processing it is omitted
bak()
{
    if [[ "$*" == N ]]
    then
        :
    else
        if
            [ -f $1.zip ]
        then
            mv -vi $1.zip BKP/$1.zip_`date +"%H-%M"`
        else
            echo "$(tput setaf 1) no "$1".zip$(tput sgr0)"
        fi
    fi
}

# The archive function, if any argument is "N", processing it is omitted. Folder
# "C" has special treatment
archive()
{
    if [ $* == N ]
    then
        :
    else
        if [ $1 == C ]
        then
            7z a -mx=9 $1.zip ../path/$1 -r -x\!$1/nope
        else
            7z a -mx=9 $1.zip $1 -r -x\!$1/bogus
        fi
    fi
}

# case #1: no arguments
if [ -z "$*" ]
then
    for i in $(seq 0 $((${#DIR[@]}-1))) # counts from 0 to array-1
    do
        echo "$(tput setaf 2) backup$(tput sgr0)"
        bak "${DIR[i]}"
        archive "${DIR[i]}"
    done
    exit $?
fi

# case #2: one argument, "N"
if [[ "$#" -eq 1 && "$1" == N ]]
then
    for i in $(seq 0 $((${#DIR[@]}-1)))
    do
        echo "$(tput setaf 1) no backup needed, removing$(tput sgr0)"
        rm -v "${DIR[i]}".zip
        archive "${DIR[i]}"
    done
    exit $?
fi

# case #3: folders as arguments with "N"
if [[ "$#" -gt 1 && "$*" == *N* ]]
then
    while [ "$#" -gt 1 ]
    do
        if [ "$1" == N ]
        then
            :
        else
            echo "$(tput setaf 1) no backup needed, removing$(tput sgr0)"
            rm -v "$1".zip
        fi
        archive "$1"
        shift
    done
# case #4: folders as arguments without "N"
else
    while [ "$#" -ge 1 ]
    do
        echo "$(tput setaf 2) backup$(tput sgr0)"
        bak "$1"
        archive "$1"
        shift
    done
fi
exit $?

查看更多
登录 后发表回答