Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.debian.user > #238168 > unrolled thread

Bash script problem

Started by"Gary L. Roach" <garyroach719@gmail.com>
First post2021-08-05 02:00 +0200
Last post2021-08-06 01:00 +0200
Articles 20 on this page of 35 — 13 participants

Back to article view | Back to linux.debian.user


Contents

  Bash script problem "Gary L. Roach" <garyroach719@gmail.com> - 2021-08-05 02:00 +0200
    Re: Bash script problem Greg Wooledge <greg@wooledge.org> - 2021-08-05 02:10 +0200
      Re: Bash script problem "Gary L. Roach" <garyroach719@gmail.com> - 2021-08-05 05:50 +0200
        Re: Bash script problem john doe <johndoe65534@mail.com> - 2021-08-05 09:00 +0200
        Re: Bash script problem <tomas@tuxteam.de> - 2021-08-05 10:10 +0200
          Re: Bash script problem Greg Wooledge <greg@wooledge.org> - 2021-08-05 13:20 +0200
            test vs. [ [was: Bash script problem] <tomas@tuxteam.de> - 2021-08-05 14:00 +0200
              Re: test vs. [ [was: Bash script problem] Greg Wooledge <greg@wooledge.org> - 2021-08-05 14:40 +0200
                Re: test vs. [ [was: Bash script problem] <tomas@tuxteam.de> - 2021-08-05 15:00 +0200
        Re: Bash script problem Greg Wooledge <greg@wooledge.org> - 2021-08-05 14:30 +0200
    Re: Bash script problem Anssi Saari <as@sci.fi> - 2021-08-05 09:40 +0200
      Re: Bash script problem Tixy <tixy@yxit.co.uk> - 2021-08-05 10:30 +0200
        Re: Bash script problem <tomas@tuxteam.de> - 2021-08-05 10:40 +0200
          Re: Bash script problem Greg Wooledge <greg@wooledge.org> - 2021-08-05 14:00 +0200
            Re: Bash script problem "Gary L. Roach" <garyroach719@gmail.com> - 2021-08-05 22:10 +0200
              Re: Bash script problem Greg Wooledge <greg@wooledge.org> - 2021-08-05 22:20 +0200
                Re: Bash script problem "Gary L. Roach" <garyroach719@gmail.com> - 2021-08-06 17:00 +0200
                  Re: Bash script problem <tomas@tuxteam.de> - 2021-08-06 17:10 +0200
              Re: Bash script problem David <bouncingcats@gmail.com> - 2021-08-06 01:40 +0200
                Re: Bash script problem Greg Wooledge <greg@wooledge.org> - 2021-08-06 02:10 +0200
                  Re: Bash script problem Polyna-Maude Racicot-Summerside <debian@polynamaude.com> - 2021-08-06 02:20 +0200
                    Re: Bash script problem Greg Wooledge <greg@wooledge.org> - 2021-08-06 02:30 +0200
                      Re: Bash script problem The Wanderer <wanderer@fastmail.fm> - 2021-08-06 03:50 +0200
                        Re: Bash script problem Greg Wooledge <greg@wooledge.org> - 2021-08-06 04:10 +0200
                Re: Bash script problem Polyna-Maude Racicot-Summerside <debian@polynamaude.com> - 2021-08-06 02:10 +0200
                  Re: Bash script problem Christian Groessler <chris@groessler.org> - 2021-08-06 02:30 +0200
                  Re: Bash script problem Christian Groessler <chris@groessler.org> - 2021-08-06 03:00 +0200
                    Re: Bash script problem Greg Wooledge <greg@wooledge.org> - 2021-08-06 03:10 +0200
                    Re: Bash script problem David <bouncingcats@gmail.com> - 2021-08-06 03:10 +0200
                  Re: Bash script problem David <bouncingcats@gmail.com> - 2021-08-06 03:00 +0200
                    Re: Bash script problem <tomas@tuxteam.de> - 2021-08-06 09:00 +0200
                Re: Bash script problem David Wright <deblis@lionunicorn.co.uk> - 2021-08-06 05:10 +0200
                  Re: Bash script problem David <bouncingcats@gmail.com> - 2021-08-06 05:50 +0200
                Re: Bash script problem Darac Marjal <mailinglist@darac.org.uk> - 2021-08-06 09:20 +0200
    Re: Bash script problem Tom Browder <tom.browder@gmail.com> - 2021-08-06 01:00 +0200

Page 1 of 2  [1] 2  Next page →


#238168 — Bash script problem

From"Gary L. Roach" <garyroach719@gmail.com>
Date2021-08-05 02:00 +0200
SubjectBash script problem
Message-ID<CIyXL-4iY-1@gated-at.bofh.it>
Hi all;

I have just recently delved into the magical world of Bash scripting and 
programmed up the following script(not finished). The object is to parse 
the Path and check for the existence of each directory. Please don't 
send back an Awk or Sed statement that is more efficient. I am having 
enough trouble with the Bash script.

Something is wrong with the logic of the if-fi statement. It is 
triggered every time through the loop. The statement A="0;  " seems to 
be true no matter what the value of A. The if statement is there to 
clear out the first item in the array that seems to be empty. Please help.

#!/bin/bash
set -x
#trap read debug

Path="/Test/gary/run/something"
IFS=/
read -a Array <<< $Path


for i  in "${!Array[@]}"
do

         A="${i} ; ${Array[i]}" #Load A
         echo "A is equal to $A"
         if [ A="0 ; " ]
         then
                 echo "continuing"
                 continue
         else
                 echo "Do rest of loop"
         fi

done

Thanks in advance.

Gary R.

[toc] | [next] | [standalone]


#238170

FromGreg Wooledge <greg@wooledge.org>
Date2021-08-05 02:10 +0200
Message-ID<CIz7r-4BD-5@gated-at.bofh.it>
In reply to#238168
On Wed, Aug 04, 2021 at 04:58:00PM -0700, Gary L. Roach wrote:
> Path="/Test/gary/run/something"
> IFS=/
> read -a Array <<< $Path

You're setting IFS permanently for the whole script.  It's usually better
to set it only for the duration of the single read command which uses
it.  Also, read should always be used with the -r option, unless you want
backslash mangling to occur.

IFS=/ read -ra Array <<< "$Path"

>         if [ A="0 ; " ]

This is incorrect, at least twice over.  You need to separate each of
the arguments of the [ command with whitespace.

if [ A = "0 ; " ]

It helps if you remember that [ is simply a fancy synonym for the test
command.  A more natural way to write this would be

if test A = "0 ; "

Next, you are comparing two constant strings, "A" and "0 ; ".  This
comparison is not useful, because they are always different strings.
If A is a variable, then you probably meant to write this:

if [ "$A" = "0 ; " ]

[toc] | [prev] | [next] | [standalone]


#238175

From"Gary L. Roach" <garyroach719@gmail.com>
Date2021-08-05 05:50 +0200
Message-ID<CICyl-6yN-3@gated-at.bofh.it>
In reply to#238170

[Multipart message — attachments visible in raw view] — view raw

Thanks for the help but I still have the problem of the if statement 
always being true. This time I enclosed the file so you can test it.

Gary R

On 8/4/21 5:04 PM, Greg Wooledge wrote:
> On Wed, Aug 04, 2021 at 04:58:00PM -0700, Gary L. Roach wrote:
>> Path="/Test/gary/run/something"
>> IFS=/
>> read -a Array <<< $Path
> You're setting IFS permanently for the whole script.  It's usually better
> to set it only for the duration of the single read command which uses
> it.  Also, read should always be used with the -r option, unless you want
> backslash mangling to occur.
>
> IFS=/ read -ra Array <<< "$Path"
>
>>          if [ A="0 ; " ]
> This is incorrect, at least twice over.  You need to separate each of
> the arguments of the [ command with whitespace.
>
> if [ A = "0 ; " ]
>
> It helps if you remember that [ is simply a fancy synonym for the test
> command.  A more natural way to write this would be
>
> if test A = "0 ; "
>
> Next, you are comparing two constant strings, "A" and "0 ; ".  This
> comparison is not useful, because they are always different strings.
> If A is a variable, then you probably meant to write this:
>
> if [ "$A" = "0 ; " ]
>

[toc] | [prev] | [next] | [standalone]


#238176

Fromjohn doe <johndoe65534@mail.com>
Date2021-08-05 09:00 +0200
Message-ID<CIFwd-8me-1@gated-at.bofh.it>
In reply to#238175
On 8/5/2021 5:47 AM, Gary L. Roach wrote:
> Thanks for the help but I still have the problem of the if statement
> always being true. This time I enclosed the file so you can test it.
>

Two things:

- Why is the var 'IFS' set above the read command?
- What are you trying to do here?

--
John Doe

[toc] | [prev] | [next] | [standalone]


#238183

From<tomas@tuxteam.de>
Date2021-08-05 10:10 +0200
Message-ID<CIGBX-Lf-1@gated-at.bofh.it>
In reply to#238175

[Multipart message — attachments visible in raw view] — view raw

On Wed, Aug 04, 2021 at 08:47:30PM -0700, Gary L. Roach wrote:
> Thanks for the help but I still have the problem of the if statement
> always being true. This time I enclosed the file so you can test it.

Please, don't top quote. It confuses the hell out of me.

Now, I think in your script

  if test A="0 ;  "

should read

  if test "$A" = "0 ;  "

or, in the square bracket version:

  if [ "$A" = "0 ;  " ]

Basically, I'm repeating what Greg wrote, in somewhat other words. Greg's
mails are worth being read twice or three times.

Look carefully. Note a couple of things:

** white spaces around the "=":
   `test' and its fancy cousin `[' are regular programs [1] invoked
   by the shell: what follows are arguments which get interpreted by
   `test', in this case, the args are "$A", = and "0 ;  ", i.e. the
   first arg, an operator (=) and the second arg. As always in the
   shell, the args HAVE TO BE SEPARATED BY WHITESPACE (huh sorry for
   raising my voice :)

** shell is not your regular php
   the shell's power (and strangeness) derives from its text replacement
   model. You have to bear that in mind. When the shell processes a
   line, it does text replacements until it thinks it's ready, then
   it invokes the command (typically a binary somewhere in $PATH, but
   it can be a builtin, an alias or a function). In your case:

     if test "$A" = "0 ;  "

   transforms to

     if test "0 ;  " = "0 ;  "

   ...so the binary `test' gets to see three args (due to the quotes).
   It dutily finishes with exit code 0, meaning "okidoki".

** watch those quotes
   this follows a bit from the above. Imagine what happens if you lose
   the quotes around "$A":

     if test $A = "0 ;  "

   now transforms to

     if test 0 ;   = "0 ;  "

   Now test sees *four* arguments: "0", ";", "=" and "0 ;  ". this
   confuses the hell out of it and it balks at you:

     bash: test: too many arguments

Shell programming is a tad different than Python, Perl, Ruby or what
you have. The textual replacement model takes some thought, but it
rewards you (as long as you use shells for what they were meant to).

I hope that gets you on track :)

And oh, in things shell, read Greg's mails. Perhaps also his wiki [2].

Cheers

[1] Nowadays this is a little white lie: most shells have them
   as builtins, but they are supposed to behave like regular
   programs, for compat. There /is/ a /bin/test, but I can't
   find a /bin/[ on my system anymore.

[2] https://mywiki.wooledge.org/BashGuide/

-- tomás

[toc] | [prev] | [next] | [standalone]


#238198

FromGreg Wooledge <greg@wooledge.org>
Date2021-08-05 13:20 +0200
Message-ID<CIJzP-2Cb-1@gated-at.bofh.it>
In reply to#238183
On Thu, Aug 05, 2021 at 10:07:12AM +0200, tomas@tuxteam.de wrote:
> [1] Nowadays this is a little white lie: most shells have them
>    as builtins, but they are supposed to behave like regular
>    programs, for compat. There /is/ a /bin/test, but I can't
>    find a /bin/[ on my system anymore.

It's in /usr/bin on Debian.

unicorn:~$ type -a test [
test is a shell builtin
test is /usr/bin/test
[ is a shell builtin
[ is /usr/bin/[
unicorn:~$ ls -ld /usr/bin/[ /usr/bin/test
-rwxr-xr-x 1 root root 60224 Sep 24  2020 '/usr/bin/['
-rwxr-xr-x 1 root root 56128 Sep 24  2020  /usr/bin/test

I'm a bit surprised they're not the same program.  And also that they're
that large.  And that different in size from each other.

The external versions of test and [ need to exist for POSIX conformance,
and also so that you can -exec them from find(1) or other similar
programs.

[toc] | [prev] | [next] | [standalone]


#238200 — test vs. [ [was: Bash script problem]

From<tomas@tuxteam.de>
Date2021-08-05 14:00 +0200
Subjecttest vs. [ [was: Bash script problem]
Message-ID<CIKcx-2Ph-3@gated-at.bofh.it>
In reply to#238198

[Multipart message — attachments visible in raw view] — view raw

On Thu, Aug 05, 2021 at 07:19:11AM -0400, Greg Wooledge wrote:
> On Thu, Aug 05, 2021 at 10:07:12AM +0200, tomas@tuxteam.de wrote:
> > [1] Nowadays this is a little white lie: most shells have them
> >    as builtins, but they are supposed to behave like regular
> >    programs, for compat. There /is/ a /bin/test, but I can't
> >    find a /bin/[ on my system anymore.
> 
> It's in /usr/bin on Debian.

Ah, there it is, thanks.

With all those young-uns shaking Unix's foundations, one never
knows ;-P

[...]

> I'm a bit surprised they're not the same program.  And also that they're
> that large.  And that different in size from each other.

Yes, that's my recollection too: [ being a symlink to test (or even both
being hardlinked together). This might betray my age...

> The external versions of test and [ need to exist for POSIX conformance,
> and also so that you can -exec them from find(1) or other similar
> programs.

I see. Do we still (seriously) care about POSIX (don't get me wrong: I'd
strongly prefer a world where we did!).

Cheers
 - t

[toc] | [prev] | [next] | [standalone]


#238206 — Re: test vs. [ [was: Bash script problem]

FromGreg Wooledge <greg@wooledge.org>
Date2021-08-05 14:40 +0200
SubjectRe: test vs. [ [was: Bash script problem]
Message-ID<CIKPf-3gC-1@gated-at.bofh.it>
In reply to#238200
On Thu, Aug 05, 2021 at 01:59:06PM +0200, tomas@tuxteam.de wrote:
> On Thu, Aug 05, 2021 at 07:19:11AM -0400, Greg Wooledge wrote:
> > The external versions of test and [ need to exist for POSIX conformance,
> > and also so that you can -exec them from find(1) or other similar
> > programs.
> 
> I see. Do we still (seriously) care about POSIX (don't get me wrong: I'd
> strongly prefer a world where we did!).

Depends on who you mean by "we".  There are a bunch of people who do
care, and a bunch of people who don't.

I'd say the Debian developers who package things like coreutils care,
at least to a certain degree.  They won't go to extreme lengths to be
POSIX compatible, but they'll mostly try to do so if it doesn't break
anything or cause an unreasonable burden.

A bigger issue is that certain packages which *should* be present for
POSIX compatibility are simply not installed by default -- specifically,
pax and ed come to mind.  I don't know who made the decision that
these packages would be "optional" instead of "standard", but it leaves
significant holes in what would otherwise be a fairly POSIX-compliant
operating system.

Then again, users who care about having POSIX-compliant systems can
simply install the extra packages they need, once they learn that they
have this option.  Maybe Debian believes that the small savings in
disk space and bandwidth outweighs the merits of being closer to POSIX
compatibility, since so few end users actually care about the latter.

I can't say which decision is the better one.

[toc] | [prev] | [next] | [standalone]


#238208 — Re: test vs. [ [was: Bash script problem]

From<tomas@tuxteam.de>
Date2021-08-05 15:00 +0200
SubjectRe: test vs. [ [was: Bash script problem]
Message-ID<CIL8B-3n6-1@gated-at.bofh.it>
In reply to#238206

[Multipart message — attachments visible in raw view] — view raw

On Thu, Aug 05, 2021 at 08:32:39AM -0400, Greg Wooledge wrote:
> On Thu, Aug 05, 2021 at 01:59:06PM +0200, tomas@tuxteam.de wrote:
> > On Thu, Aug 05, 2021 at 07:19:11AM -0400, Greg Wooledge wrote:
> > > The external versions of test and [ need to exist for POSIX conformance,
> > > and also so that you can -exec them from find(1) or other similar
> > > programs.
> > 
> > I see. Do we still (seriously) care about POSIX (don't get me wrong: I'd
> > strongly prefer a world where we did!).
> 
> Depends on who you mean by "we".

:-)

>                                  There are a bunch of people who do
> care, and a bunch of people who don't.

Yes, and I see that as a problem.

> I'd say the Debian developers who package things like coreutils care,
> at least to a certain degree.  They won't go to extreme lengths to be
> POSIX compatible, but they'll mostly try to do so if it doesn't break
> anything or cause an unreasonable burden.

[...]

> I can't say which decision is the better one.

I think this "soft POSIX compliance" might kill POSIX in the long run.
Since everyone feels free to route around his/her personal pain points,
there's little collective motivation to actually /fix/ them, and it
might drift slowly into irrelevance.

Now I'm not a 100% fan of POSIX /per se/ but I see the value in
written standards. Standards processes can seem at times clumsy, but
they force people to think about interfaces and specifications.

Otherwise it's what we have now with WHATWG's HTML5 "living standard",
which will end up with "whatever Google implements". Not much better,
in my eyes, than the bad old times of Microsoft dominance.

Cheers
 - t

[toc] | [prev] | [next] | [standalone]


#238205

FromGreg Wooledge <greg@wooledge.org>
Date2021-08-05 14:30 +0200
Message-ID<CIKFz-3dJ-1@gated-at.bofh.it>
In reply to#238175
On Wed, Aug 04, 2021 at 08:47:30PM -0700, Gary L. Roach wrote:
> Thanks for the help but I still have the problem of the if statement always
> being true. This time I enclosed the file so you can test it.

You didn't make the changes that I told you to make yesterday.  But
this has already been covered in detail, by myself and others.  Let's
move on to the bigger problems.

I can't tell what algorithm you're trying to use here, but it doesn't
look like it actually *works*.  Let's go back to the beginning.

You're writing a script that wants to check that all of the components
of a pathname actually exist, right?  So your input is something like

/usr/local/bin/youtube-dl

And you want to check whether /usr exists, and whether /usr/local exists,
and so on.

But what you've done is break the input into the following list of
words:

"" (the empty string)
usr
local
bin
youtube-dl

This isn't actually helpful.  You don't want to check wither "local"
is a directory.  You want to check whether "/usr/local" is a directory.

So, let's try to write a script that actually solves the problem.  We'll
start by checking whether the whole input as given to us is an existing
file system entry of some kind.  If it is, then we're already done --
all of the components exist, and there's nothing more to check.

If the input isn't an existing entry, then we'll strip off the last
component, check again, and so on until we reach a pathname that *does*
exist.

Here's a rough first approximation which does those things.  It may
not act precisely how you would like in all of the corner case inputs,
so some adjustments may be desirable.  But it's a good starting point.


#!/bin/bash

# If the input exists, we're done.
if [[ -e "$1" ]]; then
  echo "<$1> exists"
  exit 0
fi

# Otherwise, keep shortening it until we find something that exists,
# or we run out of pathnames to try.
f="$1"
echo "<$f> does not exist"
while [[ "$f" = */* ]]; do
  f="${f%/*}"
  if [[ -e "$f" ]]; then
    echo "<$f> exists"
    break
  else
    echo "<$f> does not exist"
  fi
done
exit 1


And, testing it:

unicorn:~$ ./foo /usr/local/bin
</usr/local/bin> exists
unicorn:~$ ./foo /usr/local/bin/rogue
</usr/local/bin/rogue> does not exist
</usr/local/bin> exists
unicorn:~$ ./foo /usr/local/sbin/rogue
</usr/local/sbin/rogue> does not exist
</usr/local/sbin> exists
unicorn:~$ ./foo /usr/local/xbin/rogue
</usr/local/xbin/rogue> does not exist
</usr/local/xbin> does not exist
</usr/local> exists
unicorn:~$ ./foo /urs/local/bin
</urs/local/bin> does not exist
</urs/local> does not exist
</urs> does not exist
<> does not exist
unicorn:~$ ./foo xyz
<xyz> does not exist

You will probably have questions about some of the syntax that I used.
Go ahead and ask them.

[toc] | [prev] | [next] | [standalone]


#238179

FromAnssi Saari <as@sci.fi>
Date2021-08-05 09:40 +0200
Message-ID<CIG8V-m5-3@gated-at.bofh.it>
In reply to#238168
"Gary L. Roach" <garyroach719@gmail.com> writes:

> Hi all;
>
> I have just recently delved into the magical world of Bash scripting
> and programmed up the following script(not finished). The object is to
> parse the Path and check for the existence of each directory. Please
> don't send back an Awk or Sed statement that is more efficient. I am
> having enough trouble with the Bash script.

Well, are trying to check the existence of each part of each path
element? So for example, first check /Test exists, then /Test/gary,
then /Test/gary/run and so on? Because just checking the directories in
$PATH is much easier, just read $PATH into an array and iterate over it
and you can use test or [ with -d to see if a directory exists.

For the weird code you have, well, I avoid bash scripting since I prefer
the zsh shell and especially its clearer array syntax. Anyways, for some
reason

[ A="0 ; " ]

is always true. It seems it probably has something to do with expansion,
quoting and the special meaning of ;. Changing the line to

if [ $A = '0 ; ' ]

seems to work.

[toc] | [prev] | [next] | [standalone]


#238188

FromTixy <tixy@yxit.co.uk>
Date2021-08-05 10:30 +0200
Message-ID<CIGVk-Ry-7@gated-at.bofh.it>
In reply to#238179
On Thu, 2021-08-05 at 10:36 +0300, Anssi Saari wrote:
[...]
> 
> [ A="0 ; " ]
> 
> is always true. It seems it probably has something to do with expansion,
> quoting and the special meaning of ;.
> 

; has no special meaning inside "". The expression is true because
there is only a single non-null argument between the [ ]

-- 
Tixy

[toc] | [prev] | [next] | [standalone]


#238189

From<tomas@tuxteam.de>
Date2021-08-05 10:40 +0200
Message-ID<CIH4Z-UG-1@gated-at.bofh.it>
In reply to#238188

[Multipart message — attachments visible in raw view] — view raw

On Thu, Aug 05, 2021 at 09:26:35AM +0100, Tixy wrote:
> On Thu, 2021-08-05 at 10:36 +0300, Anssi Saari wrote:
> [...]
> > 
> > [ A="0 ; " ]
> > 
> > is always true. It seems it probably has something to do with expansion,
> > quoting and the special meaning of ;.
> > 
> 
> ; has no special meaning inside "". The expression is true because
> there is only a single non-null argument between the [ ]

Yes, well put. As much as

  [ foobarbazxy ]

is always true :-)

I always recommend `echo' to those who want to "see" argument
expansion before pulling out their hair. Try

  echo A="0 ;  "
  => A=0 ;

Since whitespace is so difficult to see, let's prepend and postpend
something (the `-n' option tells echo to not output a newline):

  echo -n '<' ; echo -n A="0 ;  " ; echo '>'
  => <A=0 ;  >

Cheers
 - t

[toc] | [prev] | [next] | [standalone]


#238202

FromGreg Wooledge <greg@wooledge.org>
Date2021-08-05 14:00 +0200
Message-ID<CIKcx-2Ph-9@gated-at.bofh.it>
In reply to#238189
On Thu, Aug 05, 2021 at 10:38:47AM +0200, tomas@tuxteam.de wrote:
> On Thu, Aug 05, 2021 at 09:26:35AM +0100, Tixy wrote:
> > ; has no special meaning inside "". The expression is true because
> > there is only a single non-null argument between the [ ]

Precisely.  But you're probably not explaining it in a way the OP will
understand.  Let's come back to that in a moment.

>   echo A="0 ;  "
>   => A=0 ;

I'm not sure that helps much.

>   echo -n '<' ; echo -n A="0 ;  " ; echo '>'
>   => <A=0 ;  >

Why not simply echo "A=<$A>" ?  (Or printf, to be safer, but we'll save
that for a different email.  The OP doesn't seem able to absorb too many
concepts at once.)

Now, as promised, How The Test Command Works.

The test command evolved over time.  There are several different original
versions with slightly different behaviors, and even modern shells offer
some extensions to the basic standard.

In order to make everything consistent, POSIX decreed that test shall work
as follows:

The first thing it does is *COUNT* the number of arguments that it
receives.  It is impossible to overstate the importance of this.  No
matter how much you think your test command looks like it should do XYZ,
it's the number of arguments that determines what it actually does.

As Tixy said, when you have

[ A="foo" ]

you are passing *one* argument to test.  (Two arguments to the [ form,
but the final ] argument gets removed, so in the end, it's one argument
that actually counts.)

When test is given one argument, what it does is check the *length*
of that argument.  If the length is 0, the expression is treated as
"false", and test exits with status 1 (false/failure).  Otherwise, if
the length is not 0, it's treated as "true", and test exits with status 0
(true/success).

It doesn't matter *what* the string is.  All of the following generate
a "true" result:

test foobar
test true
test false
test 0
test 1
test A=B
test 2+2=5
test 'your mother was a hamster'
test "$a=$b"

It doesn't matter what the argument is, as long as it's not the empty
string.  In that last example, it doesn't even matter what $a and $b
expand to.  We're guaranteed there's at least an = sign in between them,
so we know it will never be an empty string.

When test is given *two* arguments, there are two valid forms that it
will look for:

test ! somestring
test -? something

That is, the first argument must be either a literal exclamation point,
or it must be a unary test operator which is spelled with a hyphen and
then some letter (-e or -d or -x, etc.).

If the first argument isn't either of those, the result is "unspecified".
It will probably be an error, unless your shell overrides it for some
reason.

unicorn:~$ test one two
bash: test: one: unary operator expected

If the first argument is ! then it simply does the reverse of the
one-argument check.  It looks at the length of the second argument.
If the second argument is the empty string, test exits with status 0
(success/true).  If the second argument is *not* the empty string, it
exits with status 1 (failure/false).

If the first argument is one of the unary operators, such as -d, then
the corresponding test is performed on the second argument.  In the case
of -d, it means "check whether the second argument is a directory".  And
so on.

There are also 3-argument and 4-argument forme, but I'm not going to
cover them here, because this is already long enough, and I'm basically
just repeating the POSIX man page with extra details and examples.

If you want to read the official documentation, it's at

https://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html

or if you prefer, you can install the manpages-posix package, and
then run "man 1posix test".


So, what does all of this actually mean?

It means you *cannot* omit the whitespace when you write your test
(or [) commands.

These are correct:

test "$a" = b
[ "$a" = b ]

These are *not* correct:

test "$a"=b
[ "$a"=b ]
["$a" = b]
["$a"=b]

And so on.

See also <https://mywiki.wooledge.org/BashPitfalls#pf10>, and the pitfall
after that, or for bonus credit, the entire BashPitfalls page.

[toc] | [prev] | [next] | [standalone]


#238223

From"Gary L. Roach" <garyroach719@gmail.com>
Date2021-08-05 22:10 +0200
Message-ID<CIRQJ-7vr-1@gated-at.bofh.it>
In reply to#238202

[Multipart message — attachments visible in raw view] — view raw

hi all;

I really appreciate all of your help. The file now works. See attached. 
Now t0 answer some questions.

First, the IFS command sets the string separator. The default values are 
space /n and one other. The / is not among them. If I don't set the 
delimiter before I do the read, the whole string is read into the first 
array slot. Not what I want. Also, it may be bad practice to set this 
globally but if it starts to cause trouble later I can just reset it to 
the default values.

Second, why am I separating out the Path the way I am doing? I need to 
check each level for existence then, if the level doesn't exist, create 
the directory, cd to the directory, set chown and -x chmod. After that 
check the next level and repeat the process until I run out of levels. 
There are other things that need to be done with files that are similar.

I want to use this .sh file to automatically set up the Amanda backup 
system . I just got burned bad because of no backup.(dumb I know). I've 
had so much trouble setting up backup systems that I gave up the last 
time. I want to write this procedure once and store it away on a flash 
drive so that the next time I get a major crash I can pull out the flash 
drive and restore things easily. The code that I furnished is a test bed 
for part of the working file and will be incorporated into a function in 
the final program. My approach may not be very elegant but if it works, 
frankly, I don't care.

To all of you:  The problem, as several of you pointed out, was with the 
if statement syntax. It is now fixed and is working fine. A copy is 
attached.

All of you help has been sincerely appreciated.


Gary R.


[toc] | [prev] | [next] | [standalone]


#238224

FromGreg Wooledge <greg@wooledge.org>
Date2021-08-05 22:20 +0200
Message-ID<CIS0q-7yz-1@gated-at.bofh.it>
In reply to#238223
On Thu, Aug 05, 2021 at 01:03:16PM -0700, Gary L. Roach wrote:
> First, the IFS command sets the string separator. The default values are
> space /n and one other. The / is not among them.

Yes, we know that.  The issue is that you are setting IFS for the
whole script, when you probably *should* be setting it only for a
single command.

Compare the following two blocks of commands:

IFS=/
read -ra array

vs.

IFS=/ read -ra array

The former is what *you* are doing.  This sets IFS permanently, for
the duration of the script or the current subshell (or function, if
you previously declared IFS to be local inside a function).

The latter is what we keep telling you to do.  You keep not doing it.

> Second, why am I separating out the Path the way I am doing? I need to check
> each level for existence then, if the level doesn't exist, create the
> directory, cd to the directory, [...]

Why can't you just mkdir -p the final directory?  This creates the
parent directories as needed.

> [...] set chown and -x chmod. After that check the
> next level and repeat the process until I run out of levels.

What do you mean by "-x chmod"?  A directory *needs* the +x permission bit
to be set in order to function properly.

file=/opt/foobar/share/foobar.conf
dir=${file%/*}
mkdir -p "$dir"
touch "$file"

You're doing *way* too much work.  It's a gigantic X-Y problem.

> I want to use this .sh file to automatically set up the Amanda backup system

I don't know Amanda, so I can't help you with that part.

[toc] | [prev] | [next] | [standalone]


#238268

From"Gary L. Roach" <garyroach719@gmail.com>
Date2021-08-06 17:00 +0200
Message-ID<CJ9uh-10P-3@gated-at.bofh.it>
In reply to#238224
On 8/5/21 1:15 PM, Greg Wooledge wrote:
> On Thu, Aug 05, 2021 at 01:03:16PM -0700, Gary L. Roach wrote:
>> First, the IFS command sets the string separator. The default values are
>> space /n and one other. The / is not among them.
> Yes, we know that.  The issue is that you are setting IFS for the
> whole script, when you probably *should* be setting it only for a
> single command.
Oops. I guess I just misunderstood what you were saying. I made the 
change to IFS=/ read ... Works fine.
>> Second, why am I separating out the Path the way I am doing? I need to check
>> each level for existence then, if the level doesn't exist, create the
>> directory, cd to the directory, [...]
> Why can't you just mkdir -p the final directory?  This creates the
> parent directories as needed.
I've been using Debian for a long time but didn't realize you could do 
that. Well back to the drawing board.
>> [...] set chown and -x chmod. After that check the
>> next level and repeat the process until I run out of levels.
>>
>> What do you mean by "-x chmod"?  A directory *needs* the +x permission bit
>> to be set in order to function properly.
Oops. The -x is a typo. S/B +x.
>> file=/opt/foobar/share/foobar.conf
>> dir=${file%/*}
>> mkdir -p "$dir"
>> touch "$file"
>>
>> You're doing *way* too much work.  It's a gigantic X-Y problem.
I agree. I'm going back through the code and rewriting most of it.
>> I want to use this .sh file to automatically set up the Amanda backup system
> I don't know Amanda, so I can't help you with that part.
>
That part I can work out with time. Again thanks for the help.

I'm 85 years old and the brain sometimes isn't as adgal as it used to 
be. The short term memory sucks.

Gary R.

[toc] | [prev] | [next] | [standalone]


#238269

From<tomas@tuxteam.de>
Date2021-08-06 17:10 +0200
Message-ID<CJ9DY-1jK-19@gated-at.bofh.it>
In reply to#238268

[Multipart message — attachments visible in raw view] — view raw

On Fri, Aug 06, 2021 at 07:52:20AM -0700, Gary L. Roach wrote:
> 
> On 8/5/21 1:15 PM, Greg Wooledge wrote:

[...]

> >>You're doing *way* too much work.  It's a gigantic X-Y problem.
> I agree. I'm going back through the code and rewriting most of it.

OTOH... this is how most learning journeys start, isn't it?

;-)

Cheers
 - t

[toc] | [prev] | [next] | [standalone]


#238228

FromDavid <bouncingcats@gmail.com>
Date2021-08-06 01:40 +0200
Message-ID<CIV7X-QV-1@gated-at.bofh.it>
In reply to#238223
On Fri, 6 Aug 2021 at 06:03, Gary L. Roach <garyroach719@gmail.com> wrote:

> Second, why am I separating out the Path the way I am doing? I need to
> check each level for existence then, if the level doesn't exist, create
> the directory, cd to the directory, set chown and -x chmod. After that
> check the next level and repeat the process until I run out of levels.
> There are other things that need to be done with files that are similar.

It sounds like you are unaware of 'mkdir -p' and 'chown -R'.
They are the standard tools for this kind of task.

'chmod -R' is less useful because it does not discriminate
between files and directories, I never understood why it
does not offer that option, because usually we need all file
permissions to not be the same as all directory permissions.

[toc] | [prev] | [next] | [standalone]


#238229

FromGreg Wooledge <greg@wooledge.org>
Date2021-08-06 02:10 +0200
Message-ID<CIVAZ-1fl-1@gated-at.bofh.it>
In reply to#238228
On Thu, Aug 05, 2021 at 08:01:22PM -0400, Polyna-Maude Racicot-Summerside wrote:
> find . -type d -exec chmod -v 0644 '{}' \;
> 
> to change the folder
> 
> find . -type f -exec chmod -v 0755 '{}' \;
> 
> to change files

You've switched the permissions around.  You want 644 on the files, and
755 on the directories.

Use + instead of \; to make them more efficient.  Also, you don't need
to quote the {} argument.  I've never been able to figure out where
that tradition came from, because I've never seen *any* shell where
it's needed.  But at least it's harmless.

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | linux.debian.user


csiph-web