Search code examples
shellfor-loopzipjobscsh

Unix Jobs command not listing background jobs


I am trying to create a simple script to zip a list of files each into its own zip file. The files are big, so I a trying to send the to background using ampersand. It works as I can see the temporary files filling up and after some time the files are created, but issuing the 'jobs' command does not list the jobs. What am I doing wrong?

#!/bin/ksh

for file in $*;do
    bash -c "zip -q $file.zip $file" &
done

Solution

  • NATIVE CSH SOLUTION

    As I said earlier, shell scripts execute in a subshell and the parent shell will not be able to list the jobs of a subshell. In order to use jobs, the jobs need to be running in the same shell.

    This can be achieved by source-ing the file. Since your default shell is csh the file should contain these lines according to the csh syntax

    # not a script. no need for shebang
    # sourcing this file **in csh** will 
    # start quiet zip jobs in the background
    # for all files in the working dir (*)
    
    foreach file in (*)
       zip -q "$file.zip" "$file" &
    end
    

    Keeping this file in an easily accessible location and running source /path/to/file will give you what you need.

    This is the only way to do it in csh for the following reasons:

    1. cannot be a shell script. jobs will not be possible
    2. csh does not support shell functions
    3. setting alias not easy due csh's foreach syntax

    But also consider a few of these alternatives

    A. The organisation allows for changing the login shell

    1. Change the shell to one that allows shell functions (e.g. to bash)
    chsh -s `which bash` $USER
    
    1. Logout and login or simply execute bash (or your shell of choice) to start a new shell
    2. Check you are in the right shell echo $0
    3. Add a function to your user-level login script (~/.bashrc for bash)
    # executing this command appends a bash function named `zipAll` to ~/.bashrc
    # modify according to your choice of shell
    cat << 'EOF' >> ~/.bashrc
    zipAll() {
        for file in *; do
            zip -q "$file.zip" "$file" &
        done
    }
    EOF
    
    1. The function zipAll should be available from the next login onwards.

    B. The organisation does not allow changing login shell

    1. Simply execute bash (or your shell of choice) to start a new shell
    2. Follow steps A3 to A4
    3. Temporarily switch to a new shell with bash (or your shell of choicd) when you need this function

    C. B; but you want to use bash (or other shell)

    I do not know if this is a good solution. Hopefully someone will point out the ill-effects of it. Hopefully your organisation simply allows you to change the login shell

    1. Seeing as your default shell is csh, add a line to ~/.cshrc to start bash (or your choice of shell)
    echo 'bash --login' >> ~/.cshrc
    
    1. Follow steps A2 to A4
    2. Copy necessary lines from existing ~/.cshrc to ~/.bashrc (or the file corresponding to your shell)

    Confusion regarding zip usage was oversight on my part. Apologies.
    NB: The syntax zip -q $file $file.zip does not work with my version. But I retain it assuming that it works on OP's system PS: The command that works with my version of zip is zip -q $file.zip file