Home > database >  Change a variable's output if a match is successful with each loop of for command
Change a variable's output if a match is successful with each loop of for command

Time:12-07

Startup action:

I am trying to make a function that I will call with .bash_functions which is sourced in my .bashrc file.

Goal:

I am trying to reduce the amount of code required. If I make a function with repeated commands that have (mostly minor) differences for each command line I end up with a HUGE function...

Purpose of function:

The function will search the current working directory for files that match an array of predefined extensions. If a file with a matching extension is found it will execute a certain customized command line. If another match is found with a different extension then another type of command must be used instead of the first command that was mentioned and so forth.

If the following files are in the current working directory:

file1.7z
file2.bz2
file3.gz
file4.tgz
file5.xz

Then running the function in a terminal will output the following lines:

7z x -o/root/file1 /root/file1.7z
tar -xvfj /root/file2.bz2 -C /root/file2
tar -xvf /root/file3.gz -C /root/file3
tar -xvf /root/file4.tgz -C /root/file4
tar -xvf /root/file5.xz -C /root/file5

Where I am at so far:

I don't yet have the array set up because I am stuck figuring out the flow to loop the commands correctly. I have the below script which does what I want however like I mentioned I want to slim it down if possible (learn some new tricks from you guys)!

untar()
{
    clear
    for i in *.*
    do
            local EXT="$(echo "${i}" | sed 's/.*\.//')"
            if [ -n "${EXT}" ]; then
            if [[ "${EXT}" == '7z' ]]; then
                if [ ! -d "${PWD}"/"${i%%.*}" ]; then mkdir -p "${PWD}"/"${i%%.*}"; fi
                echo 7z x -o"${PWD}"/"${i%%.*}" "${PWD}"/"${i}"
            elif [[ "${EXT}" == 'bz2' ]]; then
                if [ ! -d "${PWD}"/"${i%%.*}" ]; then mkdir -p "${PWD}"/"${i%%.*}"; fi
                echo tar -xvfj "${PWD}"/"${i}" -C "${PWD}"/"${i%%.*}"
            elif [[ "${EXT}" == 'gz' ]]; then
                if [ ! -d "${PWD}"/"${i%%.*}" ]; then mkdir -p "${PWD}"/"${i%%.*}"; fi
                echo tar -xvf "${PWD}"/"${i}" -C "${PWD}"/"${i%%.*}"
            elif [[ "${EXT}" == 'tgz' ]]; then
                if [ ! -d "${PWD}"/"${i%%.*}" ]; then mkdir -p "${PWD}"/"${i%%.*}"; fi
                echo tar -xvf "${PWD}"/"${i}" -C "${PWD}"/"${i%%.*}"
            elif [[ "${EXT}" == 'xz' ]]; then
                if [ ! -d "${PWD}"/"${i%%.*}" ]; then mkdir -p "${PWD}"/"${i%%.*}"; fi
                echo tar -xvf "${PWD}"/"${i}" -C "${PWD}"/"${i%%.*}"
            fi
        fi
    done;
}

Required to function:

Essentially, two different tar commands and a single 7z command are needed (as far as i can come up with anyways)

Command 1: tar -xvf <target.{gz,tgz,xz}> -C <output folder> 
Command 2: tar -xvfj <target.bz2> -C <output folder> 
Command 3: 7z x -o<output folder> <target.7z>

Any ideas you can throw my way?

CodePudding user response:

Since you're familiar with parameter substitution I'd start with eliminating the overhead of the dual subprocess invocations for finding EXT; shorter code but also a performance improvement as this doesn't require spawning/cleaning-up any subprocesses (for each pass through the loop):

local EXT="${i##*.}"

NOTE: this assumes all files have a single extension (eg, .tgz instead of tar.gz) otherwise OP may need to add more logic to determine how to process files with multiple extensions (eg, abc.tar.gz vs a.b.c.tar.gz)

Next idea would be to pull the mkdir logic out by itself; this eliminates 4 mkdir lines:

if [ ! -d "${PWD}"/"${i%%.*}" ]; then mkdir -p "${PWD}"/"${i%%.*}"; fi

# or

[[ ! -d "${PWD}"/"${i%%.*}" ]] && mkdir -p "${PWD}"/"${i%%.*}"

Small detour ...

OP has mentioned wanting to use an array to manage a list of extensions and while such an approach is doable it would also require some thought on how to store and reference the associated commands.

Assuming this will be the only piece of code that needs to process a list of extensions I'd probably opt for 'hardcoding' the logic for each extension (as opposed to storing in a resource/config file and then loading into an array). Net result, stick with current approach but with a few improvements.

Back to code (re)design ...


Next idea would be to collapse the tar calls into a single call with a test for bz2; this eliminates 3 tests and 3 tar lines:

if [[ "${EXT}" == '7z' ]]; then
     echo 7z x -o"${PWD}"/"${i%%.*}" "${PWD}"/"${i}"
else
     jflag=""
     [[ "${EXT}" == 'bz2' ]] && jflag="j"
     echo tar -xvf${jflag} "${PWD}"/"${i}" -C "${PWD}"/"${i%%.*}"
fi

Personally, I'd probably opt for a case statement:

case "${EXT}" in
    7z)
         echo 7z x -o"${PWD}"/"${i%%.*}" "${PWD}"/"${i}"
         ;;
    *)
         jflag=""
         [[ "${EXT}" == 'bz2' ]] && jflag="j"
         echo tar -xvf${jflag} "${PWD}"/"${i}" -C "${PWD}"/"${i%%.*}"
         ;;
esac

Pulling this all together:

untar()
{
    clear
    local EXT

    for i in *.*
    do
        EXT="${i##*.}"

        [[ ! -d "${PWD}"/"${i%%.*}" ]] && mkdir -p "${PWD}"/"${i%%.*}"

        case "${EXT}" in
            7z)
                 echo 7z x -o"${PWD}"/"${i%%.*}" "${PWD}"/"${i}"
                 ;;
            *)
                 jflag=""
                 [[ "${EXT}" == 'bz2' ]] && jflag="j"
                 echo tar -xvf${jflag} "${PWD}"/"${i}" -C "${PWD}"/"${i%%.*}"
                 ;;
        esac
    done
}

CodePudding user response:

Posting this as another example for others to see that I came up with after seeing the great example by markp-fuso.

I added zip files to the list this time.

untar()
{
    clear
    local EXT

    for i in *.*
    do
        EXT="${i##*.}"

        [[ ! -d "${PWD}"/"${i%%.*}" ]] && mkdir -p "${PWD}"/"${i%%.*}"

        case "${EXT}" in
            7z|zip)
                7z x -o"${PWD}"/"${i%%.*}" "${PWD}"/"${i}"
                 ;;
            bz2|gz|xz)
                jflag=""
                [[ "${EXT}" == 'bz2' ]] && jflag="j"
                tar -xvf${jflag} "${PWD}"/"${i}" -C "${PWD}"/"${i%%.*}"
                 ;;
        esac
    done
}
  • Related