ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Why does the second script with ! still return the output of
Code:
date
command?
Actually I am trying to change this script
Code:
#!/bin/dash
while true; do
open=$(ls -a --group-directories-first --file-type | grep -v "^\.[a-zA-Z0-9]\|^\./" | dmenu -p "dmenuFM: ")
if [ -d "$open" ]; then
cd "$open"
else
if [ ! -z "$open" ]; then
xdg-open "$open"
fi
break
fi
done
to
Code:
#!/bin/dash
while true; do
open=$(ls -a --group-directories-first --file-type | grep -v "^\.[a-zA-Z0-9]\|^\./" | dmenu -p "dmenuFM: ")
[ -d "$open" ] && cd "$open" || xdg-open "$open" && break
done
But the way I am changing is not working as expected.
#!/bin/dash
while true; do
open=$(ls -a --group-directories-first --file-type | grep -v "^\.[a-zA-Z0-9]\|^\./" | dmenu -p "dmenuFM: ")
if [ -d "$open" ]; then
cd "$open"
else
if [ ! -z "$open" ]; then
xdg-open "$open"
fi
break
fi
done
Just my US$0.02 but, assuming that the original script is actually working, taking the clear "if-then-else" constructs and trying to turn them into a one-liner may not be making the script simpler. Shorter, sure, but not necessarily simpler. Clear-and-simple-to-understand beats clever any day. Will the one-liner make sense when the script is visited again in months or a year from now?
The "usual" mistake here is: the if/then/else construct cannot be replaced by && || or something similar, that works differently (there are some cases when they produce the same result and there are some other cases when they produce different result).
As it was already mentioned, if the && || && construct is confusing, use if/then/elif/else. That is much more readable and more easily understandable.
But that wont work with the actual code involving cd, because the directory change is lost when the sub-shell ends.
Still the actual code can be simplified...
I had expected to see someone pointing out that "! -z" is a longer way to write "-n", though that check possibly isn't even needed - an empty value comes from pressing Esc in dmenu, right? So just move the assignment into the while check and rely on the dmenu exit status to abort the loop instead.
This allows there to be a single inverted test of "not a directory" which can bring that part down to a couple of lines, (the break removes the need for an explicit else clause).
Also, the grep is unnecessary; far easier to remove the -a option so the offending items never get output, then prefix the "..".
Also I haven't checked but it may be necessary to explicitly set an ls quoting style. (This script wont handle filenames with newlines in, but that's a limitation with dmenu too?)
Code:
#!/bin/dash
while selection=$( ( echo ".." ; ls -1 --g --file-type ) | dmenu -p "dmenuFM: " )
do
if [ ! -d "$selection" ]; then echo xdg-open "$selection" ; break ; fi
cd "$selection" || echo "error: failed to cd [$selection] in [$PWD]"
done
Looking at what the code is doing, I think I'd have gone with a 'case' construct. Maybe, something along the lines of:
Code:
while [ -z "$open" ]
do
if open=$( ls --group-directories-first -Fd * | dmenu -p select: -l 10 ); then
case "$open" in
"") : ;;
*/) cd "$open" ; unset open ;;
*) xdg-open "$open" ;;
esac
else
break
fi
done
if [ -n "$a" ]; then echo empty; else echo noempty; date; fi
Another suggestion for the loop:
Code:
while
open=$(ls -a --group-directories-first --file-type | grep -v "^\.[a-zA-Z0-9/]" | dmenu -p "dmenuFM: ")
[ -d "$open" ]
do
cd "$open"
done
if [ -n "$open" ]
then
xdg-open "$open"
fi
Last edited by MadeInGermany; 08-05-2022 at 07:29 AM.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.