LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 12-27-2023, 02:15 AM   #1
oldpink
Member
 
Registered: Feb 2004
Posts: 34

Rep: Reputation: 1
Unhappy How to check parameters in Bash?


I tried to find the answer for this with searches here and everywhere else that I could, but it's hard to even know how to phrase the search to do that, so I'm asking here directly, where I can clarify to someone much more knowledgeable than I am.
What I'm trying to do is to check that each parameter in a Bash script is correct, including if each parameter is wildcarded, then halt the entire script if any of the parameters is incorrect.
The problem is that parameter expansion before I can even run the script is interfering with this.
For example, I start the script with these lines:

for x in $@ ; do
case $x in
*.jpg|*.mp4)
echo OKAY
;;
*)
echo NOT OKAY
exit
;;
esac
done

What I'm trying to do is to get it to stop the script entirely if even one of the parameters ($@) does not match the choices in the first case strings.
For example, if I use *.j?g *.mp? together as the parameters, it should continue with the rest of the script, but if *.jpg *.jp are the parameters, I need the script to detect the incorrect *,jp parameter and exit.
In fact, if I pass one of the parameters using a wildcard that I want to stop the script, it only stops if a file matching that file spec exists to match the wildcard and expand it.
Obviously, I need it to halt whether that file exists or not.
I've tried everything that I can think of, including "set -f" to turn off expansion, but the problem is that only works if I have "set -f" switched on before the script even starts, obviously because otherwise the parameters are expanded on the command line before the script executes.
I'm essentially in a chicken-and-the-egg situation with parameter string checking on this one.
My apologies if the way that I'm asking my question is overly verbose or poorly worded, but I'm still hoping that someone can help with the answer on this one.

EDIT: I found that I actually have no problem accomplishing what I want with this script if I execute it from the bash shell first, but I use TCSH as my regular shell, and that is when it fails.
I know that's unconventional for most people, but I started on TCSH nearly thirty years ago and find that more comfortable than bash for my login shell.
Is there something that can work around that?

Last edited by oldpink; 12-27-2023 at 02:57 AM.
 
Old 12-27-2023, 03:29 AM   #2
timl
Member
 
Registered: Jan 2009
Location: Sydney, Australia
Distribution: Fedora,CentOS
Posts: 751

Rep: Reputation: 156Reputation: 156
I had a similar problem recently. Add this as the first line in the script:

Code:
#!/bin/bash
 
Old 12-27-2023, 03:36 AM   #3
GazL
LQ Veteran
 
Registered: May 2008
Posts: 6,914

Rep: Reputation: 5032Reputation: 5032Reputation: 5032Reputation: 5032Reputation: 5032Reputation: 5032Reputation: 5032Reputation: 5032Reputation: 5032Reputation: 5032Reputation: 5032
To the best of my knowledge there's no way to tell whether arguments passed from the parent shell were the results of an expansion or not. There are the nullglob and failglob shell options, but they must already set in the parent shell.

It's just the way shell expansion and argument passing works on UNIX.

What folks normally do is check whether the file exists and is of the correct type before acting on it. Remember, file extensions are a microsoft thing. Though we tend to still use them in UNIXland, it's only by convention and they're not really significant.
 
Old 12-27-2023, 03:48 AM   #4
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,976

Rep: Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337
Yes, a lot of questions. First of all, you need to decide if you want tcsh or bash, the syntax is different.
Next, the shell (terminal) will evaluate the command and will replace *.jpg and similar expressions, if possible (see shell expansion, failglob and others).
So in your case $@ will not contain *.jpg, but all the jpg files. Furthermore you ought to use shellcheck to check your script.
I guess you only need to check if the passed parameters are valid files, do not need to take care of shell expansion at all.
Additionally please use code blocks to post your scripts.

Last edited by pan64; 12-27-2023 at 03:50 AM.
 
Old 12-27-2023, 06:34 AM   #5
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,874
Blog Entries: 1

Rep: Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871
As a start, correct this:
Code:
- for x in $@ ; do
+ for x in "$@" ; do
 
Old 12-27-2023, 10:09 AM   #6
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,816

Rep: Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211
Code:
#!/bin/bash
for x in "$@"
do
  case $x in
  ( *.j?g | *.mp? )
    echo "OKAY"
  ;;
  ( * )
    echo "NOT OKAY"
    exit
  ;;
  esac
done
The script arguments are evaluated+expanded already by the invoking shell unless protected by quoting or by using set -f or set noglob

The glob pattern in case-esac follows the same rules as the argument expansion, so here you might not see any difference if expansions occurred or not.

Last edited by MadeInGermany; 12-27-2023 at 10:23 AM.
 
Old 12-27-2023, 10:15 AM   #7
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,874
Blog Entries: 1

Rep: Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871Reputation: 1871
Code:
- echo "OKAY"
+ echo "filename $x OKAY"

Last edited by NevemTeve; 12-27-2023 at 10:16 AM.
 
Old 12-27-2023, 11:03 AM   #8
oldpink
Member
 
Registered: Feb 2004
Posts: 34

Original Poster
Rep: Reputation: 1
Quote:
Originally Posted by MadeInGermany View Post
Code:
#!/bin/bash
for x in "$@"
do
  case $x in
  ( *.j?g | *.mp? )
    echo "OKAY"
  ;;
  ( * )
    echo "NOT OKAY"
    exit
  ;;
  esac
done
The script arguments are evaluated+expanded already by the invoking shell unless protected by quoting or by using set -f or set noglob

The glob pattern in case-esac follows the same rules as the argument expansion, so here you might not see any difference if expansions occurred or not.
The part about the shell evaluating/expanding the arguments isn't a problem if I run the script from within a bash shell.
The problem is that I use TCSH as my login shell,and it does the expansion/evaluation before the script starts, and I see no way to stop that before the script.
Can I assume that there's no temporary option from within TCSH that I can use on the way to running the Bash scrip that sidesteps this?
Yes, I know well that TCSH is a far less popular shell than Bash, but I'm much more comfortable using it for my login shell, with Bash for all of my scripts.
Thanks for the suggestions and information up to this point from everyone.
 
Old 12-27-2023, 11:14 AM   #9
wpeckham
LQ Guru
 
Registered: Apr 2010
Location: Continental USA
Distribution: Debian, Ubuntu, RedHat, DSL, Puppy, CentOS, Knoppix, Mint-DE, Sparky, VSIDO, tinycore, Q4OS, Manjaro
Posts: 5,713

Rep: Reputation: 2721Reputation: 2721Reputation: 2721Reputation: 2721Reputation: 2721Reputation: 2721Reputation: 2721Reputation: 2721Reputation: 2721Reputation: 2721Reputation: 2721
When you type in the command and hit enter it is already too late to examine the command line parameters unexpanded. At that point, with the enter key hit, the running shell (and it may be different from the script shell) expanded any globs.

You might want to rethink this, and instead examine the individual list entries that result and act on that basis.
 
Old 12-27-2023, 11:31 AM   #10
oldpink
Member
 
Registered: Feb 2004
Posts: 34

Original Poster
Rep: Reputation: 1
I dug around a bit in the man page for TCSH, where I found information about the "noglob" variable.
I then found that simply doing "set noglob" on the command line immediately before running the script gives me exactly what I want, with the script stopping with any incorrect wildcard and operating normally with correct ones.
Thanks for the help everyone, and finding this answer could be useful for the few other TCSH users out there.
This is now going marked as unquestionably solved.
 
Old 12-27-2023, 01:39 PM   #11
oldpink
Member
 
Registered: Feb 2004
Posts: 34

Original Poster
Rep: Reputation: 1
Just one more little comment that makes this solution now work much more easily:
I have several bash scripts that need to work on the same principle as the one that I mentioned, so I solved it with a simple alias that operates within a subshell, setting the "noglob" variable, running the script, which allows the "noglob" variable to automatically switch off at the conclusion of the alias.
The alias looks like this:
alias GAME_CAMERA '( set noglob ; GAME_CAMERA.sh \!:* )'
This is basically an alias wrapper for a Bash script, and it works perfectly after testing every way possible.
This might be useful to others in a similar situation of globbing causing problems with their own Bash scripts run from TCSH.
 
Old 12-28-2023, 12:45 AM   #12
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,976

Rep: Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337Reputation: 7337
I guess basically the shell can do the globbing and you need to check only the result. There is no reason to do that by yourself instead of the shell. But anyway, if you wish you can do that.
This was the world of Windows, where each program handled this itself (instead of the shell).
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Bash: Continuously check processes running or not with some parameters ThorinTheFirst Programming 15 01-16-2022 06:21 AM
edit a file /etc/fstab , what parameters can be changebale and which parameters lenin99 Debian 7 01-24-2017 04:03 AM
[SOLVED] Why there are two separate parameters in /proc/sys/net/ipv4/ for security parameters gprathap1121@gmail.com Linux - Security 4 07-14-2014 12:41 AM
Partition check, check double check Vincentius Linux - General 0 12-25-2004 05:47 AM
Boot disk; check. CD in drive; check. Doesn't work; check. Hal DamnSmallLinux 7 02-04-2004 02:10 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 06:30 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration