Page 1 of 1

Run pluma from script and wait for file close

Posted: Mon Sep 18, 2017 4:32 pm
by rustleg
I have this in a bash script (Mint 17):

Code: Select all

#! /bin/bash
if [ -e /usr/bin/pluma ] ; then pluma myfile.txt ; fi
< rest of script >
I want to be able to edit the file in pluma, close the file and then have the rest of the script process the modified file. This works ok if pluma is not already open editing another file. But if pluma is already open the file opens in another tab in the existing instance of pluma instead of starting a new instance of pluma and execution of the script doesn't wait for the file to be closed. In this scenario is it possible to pause execution of the rest of the script until the file is closed?

Re: Run pluma from script and wait for file close

Posted: Mon Sep 18, 2017 5:47 pm
by xenopeek
I don't think Pluma can do this. You need a text editor that supports the option to block till the opened file is closed again. Depending on your version, Xed (xed -w [i]filename[/i]), Gedit (gedit -w [i]filename[/i]) and Kate (kate -b [i]filename[/i]) do support this. Those commands will not complete until you've closed the file, regardless of existing open windows. Pluma doesn't have an option for this AFAIK.

Re: Run pluma from script and wait for file close

Posted: Tue Sep 19, 2017 1:34 am
by rustleg
Ok thanks. I'll leave it until I decide to upgrade to Mint 18 or 19. I'll just have to run a separate script after the edit.

Re: Run pluma from script and wait for file close

Posted: Tue Sep 19, 2017 11:41 am
by BG405
You could always install gedit, I usually do on non-Cinnamon systems. Although I prefer Kate I do also have gedit installed on my KDE systems. Then you could use that for your scripts.

Re: Run pluma from script and wait for file close

Posted: Tue Sep 19, 2017 3:14 pm
by rustleg
I installed gedit but found that there was no -w option. This is the same as the man page on my Mint 17:
http://linuxcommand.org/lc3_man_pages/gedit1.html

Re: Run pluma from script and wait for file close

Posted: Tue Sep 19, 2017 3:28 pm
by xenopeek
Uninstall gedit and gedit-common and then install it like this:
sudo apt-get install gedit/trusty

Linux Mint 17 used a much older version of Gedit, on which Pluma is also based (hence the missing option). With the above command you can install the newer version of Gedit.

Re: Run pluma from script and wait for file close

Posted: Wed Sep 20, 2017 3:12 pm
by rustleg
I have installed gedit/trusty and it works as you say, many thanks. The fact that there are 2 gedits and the ubuntu entry in sources refers to trusty but Mint 17 picks up a different one is quite a subtle point, way beyond my pay grade. I dub you a guru :D

Re: Run pluma from script and wait for file close

Posted: Wed Sep 20, 2017 10:38 pm
by lmuserx4849
rustleg wrote:Ok thanks. I'll leave it until I decide to upgrade to Mint 18 or 19. I'll just have to run a separate script after the edit.
xenopeek is right, need a different editor. The pluma from your script is just passing the file to the already running instance of pluma and terminating.

A possible quick fix is to add a read to the script like version 1 or 2 below. When you are done editing the file type any key in version 1 or "y" in version 2.

Code: Select all

# Version 1
read -re -n1 -p 'Press any key to continue... '

# Version 2
while true; do
  # The capital N is just to indicate to the user that n is the default when you hit Enter. 
  # The colon-dash parameter expansion substitutes n if empty.
  # n is the default. If you accidently hit a key the rest of the script won't run. You have to type y for the script to continue.  
  
  read -re -n1 -p 'Continue [y|N]: '    
  [[ ${REPLY:-n} == [yY] ]] && break   
done
See: parameter expansion

Re: Run pluma from script and wait for file close

Posted: Thu Sep 21, 2017 3:27 am
by rustleg
lmuserx4849 wrote: A possible quick fix is to add a read to the script like version 1 or 2 below ...

Code: Select all

while true; do
  # The capital N is just to indicate to the user that n is the default when you hit Enter. 
  # The colon-dash parameter expansion substitutes n if empty.
  # n is the default. If you accidently hit a key the rest of the script won't run. You have to type y for the script to continue.  
  
  read -re -n1 -p 'Continue [y|N]: '    
  [[ ${REPLY:-n} == [yY] ]] && break   
done
Thanks - nice info re the colon-dash. I run this script from an icon on the desktop so I'm not opening a terminal. I could do but I prefer just to see the editor then when the editor quits the rest of the script does its magic silently.

Re: Run pluma from script and wait for file close

Posted: Thu Sep 21, 2017 12:08 pm
by lmuserx4849
rustleg wrote: Thanks - nice info re the colon-dash. I run this script from an icon on the desktop so I'm not opening a terminal. I could do but I prefer just to see the editor then when the editor quits the rest of the script does its magic silently.
Agree :-)

Just to put it out there, a quick fix to the quick fix, the read could be replaced with dialog or kdialog (kde).

Code: Select all

if ! dialog --title "Modify File" \
            --yesno "Continue?" 0 0
then
  exit
fi

#rest of script here
dialog(1) - Linux man page

Re: Run pluma from script and wait for file close

Posted: Wed Sep 27, 2017 9:50 pm
by Termy
You may find the shell builtin wait helpful; see help wait. That said, you can write a while loop which looks for an open file using lsof; if it detects it as no longer opened (you've closed it), then break from the loop and continue. Here would be my approach, using the Bourne Shell:

Code: Select all

#!/bin/sh

for DEP in /bin/sleep /usr/bin/pluma /usr/bin/lsof
do
        [ -x "$DEP" ] || exit 1
done

FILENAME="$*"

while /usr/bin/pluma "$FILENAME"
do
        /bin/sleep 1s
        /usr/bin/lsof "$FILENAME" 2>&1 > /dev/null || break
done
Then you need only run the script as: scriptname FILE

Re: Run pluma from script and wait for file close

Posted: Thu Sep 28, 2017 10:37 am
by rustleg
Termy thanks for the script. I like to understand a script before I use it, so please bear with me. Please let me know where I am making an error.

I think I could dispense with the top "for DEP" loop, once the existence of the files has been established it won't do anything useful.

To test the logic in the while loop I tried
lsof /mnt/My/TempMy/xxx.txt || echo "YYY"
where the file /mnt/My/TempMy/xxx.txt was being edited by xed, and it returned nothing. (I tested this in Mint 18.2 as I was running this at the time). If the file didn't exist lsof would return an error. So even if it exists and is being edited it doesn't seem to return anything useful. Is the purpose to return an error status?

Also isn't the while trying to keep reinvoking pluma every one second? Is this necessary and possibly resource heavy?

This is not to denigrate your effort to help which I am most grateful for.

Re: Run pluma from script and wait for file close

Posted: Thu Sep 28, 2017 12:36 pm
by Termy
No problem. I understand and was/am the same way.

I like to flesh out my scripts/programs; it's a force of habit. I write them to account for whatifs, based on different setups. If you were to run it, you can have no dependency checking if you wanted.

The while loop wouldn't keep loading pluma, but it would were it within the actual code block and not part of the condition, or if something in the loop didn't specify that it should break, such as the lsof check. Every second the loop checks for the file you were working on being active; if it's not found, a non-zero exit status is given, which || picks up on, and thus breaking from the loop and ending the script. It would keep loading pluma, however, if another process were using the same file; see below for oversight.

The lack of output while xed was editing the specified file was intentional; you'd see output if you stopped using the file, regarding your test. An oversight on my part though, is that I forgot you might have the file open by another process, such as a different editor; in this case, you'd want to do a bit more, but this would likely suffice, unless it's a configuration file for a program which gets frequently used.

While tests that something is true or false (boolean), and if it's either one, break from the loop, otherwise continue iterating through each command in the block. A simpler example:

Code: Select all

while true
do
        echo "This is a test."
done
That would infinitely repeat the echo command, because true will always exit 0, and while is testing for success (0 exit status). The condition for breaking out of the loop is never met. Another common example:

Code: Select all

declare -i A=1
while [ $A -le 10 ]
do
        echo "$A"
        A+=1
done
The first line declares the variable A as an integer, allowing the use of NAME+=n to increment variable NAME by n. The condition to continue looping, is that A should be less than or equal to 10, otherwise the condition is no longer met, thus breaking from the loop.

Another approach:

Code: Select all

evince & A=$!
while ps $A &> /dev/null || break
do
        :
done
I used evince as an example here -- a viewer for things like PDF documents. This will load evince, putting it into the background (it's a GUI, so you'll still be able to access it), thus allowing you to capture its PID into the A variable, which then gets tested for in the while loop. The loop's focus isn't the contents, it's the condition. For as long as ps detects the PID (&> /dev/null omits output), it'll continue checking for it, otherwise it'll break from the loop. The : is just shorthand for true, so it basically does nothing. It's a similar concept, but for a different purpose.

Hope that all helps you understand the code. :)

Re: Run pluma from script and wait for file close

Posted: Fri Sep 29, 2017 11:40 am
by rustleg
Thanks for all the explanations. I must admit I don't like Bash much. I find it most unintuitive. I guess if I was using it a lot I'd remember the detail. I've never discovered a book that I found useful. The nearest I came is the O'Reilly bash Cookbook. I usually have to use google a lot and look for similar examples mostly in stack exchange.