0

I have been trying to get various versions of this to work:

[[ -e "~/usersl" ]] && { user=`cat ~/usersl`; echo Username: $user; } || { read -p "Username:" user; echo $user > ~/usersl; }

The main goal is to have a if..then..else all in one line. From what I have read on this site and others, this should work. It should check to see if the usersl file exists and if it does then it prints out the detected username and populates the $user variable. If the usersl file doesn't exist then it should ask for the username and populate the variable at the same time then record the new username into a file. Once that has been done the next tiem the command is ran the file already exists and it just displays the username and propagates the variable. Hope my explanation isn't overly complicated but the task is very simple.

Any help is much appreciated

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Jeff82
  • 147
  • 10
  • 2
    `&&` is not an exact identical replacement to `if`. Don't use it as if it were. – Charles Duffy Jun 29 '16 at 01:11
  • The accepted answer in http://stackoverflow.com/questions/30766270/why-use-short-circuiting-boolean-logic-rather-than-if-then-else-in-bash covers the bug in this formulation, btw. – Charles Duffy Jun 29 '16 at 01:16
  • that said, `[[ -e "~/usersl" ]]` will always fail: Quoting the `~` prevents its expansion, so it isn't treated as identical to `$HOME`. – Charles Duffy Jun 29 '16 at 01:17
  • How would I get this into one line then. It looks like the typical if..then..else cannot have multiple commands per section. – Jeff82 Jun 29 '16 at 01:20
  • 1
    `if [[ -e ~/usersl ]]; then user=$(<~/usersl); echo "Username: $user"; else read -p "Username:" user; echo "$user" >~/usersl; fi` <- all one line. Where'd you get the idea it couldn't be done? – Charles Duffy Jun 29 '16 at 01:20
  • When i run that, it asks for the username over and over again eventhough the usersl file exists – Jeff82 Jun 29 '16 at 01:22
  • 1
    err, I typo'd it a bit in the above, since corrected -- it was just `~/users` in one place, vs `~/usersl` in another, but that bug is nothing to do with the `if` syntax. – Charles Duffy Jun 29 '16 at 01:22
  • btw, http://shellcheck.net/ finds your bug here programmatically -- using it might have saved you from human-driven snark. – Charles Duffy Jun 29 '16 at 01:25
  • If this has to be done in a single command. Why not write a separate shell script that can be used as a command? Then you can just reference the command. – WSimpson Jun 29 '16 at 01:38

1 Answers1

3

Your most immediate bug had nothing to do with the conditional syntax, but was caused by a bug in how you were quoting around your test:

if [[ -e ~/usersl ]]; then
  user=$(<~/usersl)
  echo "Username: $user"
else
  read -p "Username:" user
  echo "$user" > ~/usersl
fi

As a one-liner, this would be:

if [[ -e ~/usersl ]]; then user=$(<~/usersl); echo "Username: $user"; else read -p "Username:" user; echo "$user" >~/usersl; fi

  • Tilde expansion is suppressed by quotes. If in doubt, write $HOME instead of ~.
  • Using a && b || c is bug-prone: If a succeeds and b tries to run but fails, you can have c run even though b was also invoked.
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441