Search code examples
bashgnu-screenquoting

GNU Screen: Open window and send command from loop in Bash script


Solved! See below

I have a script that should do the following:

  1. Read a line from a file, the line takes the form ftp://user:[email protected]/path/to/dir/
  2. Launch a new instance of lftp in a new window in a given GNU screen session that uploads the contents of the directory from which the script was launched, to the directory given in 1.
  3. Repeat 1-2 with the next line in the file, for however many lines there are.

Since the default working directory of the screen session may be different than the current working directory, the script must change to the current working directory first.

At the moment the script looks something like the following:

#!/bin/bash

SERVERLIST=$1
INITIAL_WD="$PWD"
SCREEN_SESSION="mysession"

if ! screen -list | grep -q "$SCREEN_SESSION"; then
    echo "Creating new screen session..."
    screen -d -m -S "$SCREEN_SESSION"
fi

while IFS='' read line || [[ -n "$line" ]] ; do
echo "Uploading to ${line}"
screen -S "$SCREEN_SESSION" -X screen 'cd $INITIAL_WD ; lftp -e "set ftp:ssl-allow false; mirror -Rvc" "$line"'
done < <(cat $SERVERLIST)

Unfortunately, this doesn't work. The script seems to execute, but the lftp command does not run... when I reattach to the screen session, there is only one window (instead of #_of_lines windows) and no uploads have been done.


Solution

  • At the moment (after some help from @Cyrus in the comments) the script looks something like the following:

    #!/bin/bash
    
    SERVERLIST=$1
    INITIAL_WD="$PWD"
    SCREEN_SESSION="mysession"
    
    if ! screen -list | grep -q "$SCREEN_SESSION"; then
        echo "Creating new screen session..."
        screen -d -m -S "$SCREEN_SESSION"
    fi
    
    while IFS='' read line || [[ -n "$line" ]] ; do
    echo "Uploading to ${line}"
    screen -S "$SCREEN_SESSION" -X chdir "$INITIAL_WD"
    screen -S "$SCREEN_SESSION" -X screen bash -c "lftp -e \"set ftp:ssl-allow false; mirror -Rvc\" \"$line\" ; exec bash"
    done < <(cat $SERVERLIST)
    

    This seems to work!