Hot answers tagged

10

it seems Bash is a Turing-complete language The concept of Turing completeness is entirely separate from many other concepts useful in a language for programming in the large: usability, expressiveness, understandabilty, speed, etc. If Turing-completeness were all we required, we wouldn't have any programming languages at all, not even assembly language. ...


10

Let's say you lack both GNU screen and tmux (and X11, and virtual consoles) but want to switch between a login shell and another interactive shell. You would first login on the console, and then start a new shell, temporarily blocking the login shell. To get the login shell back to do some work there, you'd do suspend. Then you would fg to get the ...


8

Grep interprets \n as a newline character. It looks like your file does not have newline characters, it has \ followed by n. To search for literal backslashes, you must double them: $ grep -o '\\n[^\\]*\\n' o.txt \n29\n \n3 days\n \n59\n \n7 days\n \n99\n \n12 days\n With GNU grep, the output can be easily cleaned up to remove the \n: $ grep -oP '(?<...


8

It depends on how complicated the output is and how much formatting needs to be maintained (eg is the first column always 8 characters long? etc). However a while loop might work cat source.tab | while read -r name id do echo "$name $id $(dbstream .... code=$id)" done You can change what happens inside the loop to format however you like eg cat source....


7

Using the command seq to generate the list over which to iterate: for nn in $(seq 1 50) ; do (cd someprefix/$nn && action) done Or, if your shell supports brace expansion: for nn in {1..50} ; do (cd someprefix/$nn && action) done


7

Aliases are only expanded if the command appears directly in the code, without any expansion. Writing things like \a, $V, $(echo a), etc. suppresses alias lookup. In addition, bash (unlike other shells) doesn't expand aliases in scripts by default anyway, so a actually does not run the alias in bash. Use a function instead of an alias. You'll need to use ...


7

With bash: shopt -s nullglob files=(/mydir/*.gz) ((${#files[@]} == 0)) || gzip -d -- "${files[@]}" With zsh: files=(/mydir/*.gz(N)) (($#files == 0)) || gzip -d -- $files Note that in zsh, without (N), like in pre-Bourne shells, csh or tcsh, if the glob doesn't match, the command is not run, you'd only do the above to avoid the resulting error message (...


6

Why don't you use case? case $text in us-east-1|us-west-2|us-west-1|eu-central-1|ap-southeast-1|etc) echo "Working" ;; *) echo "Invalid option: $text" ;; esac


6

Yes, you may nest if-statements to your heart's content. The issue with your code is, as pointed out in comments to the question, the two exit statements. Taking a branch that triggers any of these will terminate the script. As far as I can see, both exit statements are superfluous and may be removed. You should also make a habit of double-quoting any ...


5

Why not make the life of the user a bit easier by not requiring them to type the name of the region at all? #!/bin/bash echo "Select region" PS3="region (1-10): " select region in "us-east-1" "us-west-2" "us-west-1" "eu-central-1" \ "ap-southeast-1" "ap-northeast-1" "ap-southeast-2" \ "ap-northeast-2" "ap-south-1" "sa-east-1" do if [[ -z $...


5

You're flattening the input into a single value. You should do list=("${@}") to maintain the array and the potential of whitespace in arguments. If you miss out the " then something like ./script.sh "a b" 2 3 4 will return a length of 5 because the first argument will be split up. With " we get $ cat x #!/bin/bash list=("${@}") echo array = ${list[*]}...


4

We can walk or swim anywhere, so why do we bother with bicycles, cars, trains, boats, planes and other vehicles? Sure, walking or swimming can be tiring, but there is a huge advantage in not needed any extra equipment. For one thing, although bash is Turing-complete, it is not good at manipulating data other than integers (not too large), strings, (one-...


4

The problem is with this: [ "$text" != 'us-east-1' -o us-west-2 -o ... ] The -o means or and you need a full condition, so it would be [ "$text" != 'us-east-1' -o "$text" != 'us-west-2' -o ... ] See how we're having to test $text each time? Your logic is also wrong; you want -a (and); if it's not "us-east-1" and it's not "us-west-2" and it's not... ...


4

Bash allows for loops that looks like the standard C for-loop: for (( i = 1; i <= 50; ++i )); do ( cd $i && action ) done Change cd $i to cd "$HOME/PATH/$i" or whatever the path is to your directories.


4

The break command allows you to break out of a loop. So you would do something like this, after setting a if [ $a -gt 50 ] then break fi


4

#!/bin/bash a=1 b=1 cd ~/PATH/ for i in $(ls -v) ;do (cd $i/ && action) && echo "completed" || echo "error" a=$((a+b)); [ "$a" -gt 50 ] && break echo "Next Folder" done


4

Nested substitution is not available in any modern Bourne-like shells except zsh: $ print -rl -- ${$(echo):-C} C $ print -rl -- ${$(echo 1):-C} 1 In other shells: A=$(nc -l 443) A=${A:-C}


4

To call a function with arguments: function_name $arg1 $arg2 The function refers to passed arguments by their position (not by name), that is $1, $2, and so forth. $0 is the name of the script itself. Example: #!/bin/bash add() { result=$(($1 + $2)) echo "Result is : "$result"" } add 1 2 Output ./script.sh Result is : 3


4

In ls $(grep file file.txt) You're using the split+glob operator incorrectly and that's where your problem lies. You don't want to insert quotes in the output of grep as that output is not interpreted as shell code (thankfully!), but you need to tune your split+glob operator. Here You don't want the glob part (the expansion of * words for instance into ...


3

You need shopt -s extglob inside the script. Your bash configuration presumably turns this on automatically for interactive shells (perhaps because you load the bash-completion package for context-sensitive completion); you need to turn it on manually inside scripts. Also make sure that your script starts with #!/bin/bash (or a variant like #!/usr/bin/...


3

The variable PATH is a special one. There are a lot of special variables (and all are all capital, so easily avoided). PATH holds a list of directories to search for commands. For fun and learning (though these are the same thing), type echo $PATH, outside of script, to see what it has in it. To fix problem do not break PATH: use a different variable name (...


3

You can perhaps do what you want using bash's readline with -i which provides an initial input to -e edit. For example, using date rather than ls as it is simpler to see: $ read -ei "$(date)" && $REPLY Mon Jul 25 13:42:47 CEST 2016 You now have the string Mon Jul 25 13:42:47 CEST 2016 as shown with the cursor at the end. You can edit this using ...


3

I think what you are trying to accomplish is very hard if not impossible, even when you can create a wrapper function to do what you want and an alias to call the wrapper instead of the actual command it all goes wrong because you usually run sudo pacman -S and sudo breaks all functions and aliases by switching contexts. But not all is lost, you can list ...


3

Commands don't change the autocomplete rules. The autocomplete rules are defined for the shell using scripts and functions and loaded when the shell is started. I am going to use bash as an example since I am familiar with that more than the other shells. The rules for autocomplete in bash are defined in the script in /etc/bash_completion and supplemented ...


3

Some reasons not to use shell scripts for large programs, just off the top of my head: Most functions are done by forking off external commands, which is slow. In contrast, programming languages like Perl can do the equivalent of mkdir or grep internally. There's no easy way to access C libraries, or make direct system calls, which means that e.g. the ...


3

One way to do this is: shopt -s nullglob for f in /mydir/*.gz; do gzip -d /mydir/*.gz break done The for loop with nullglob set on will only execute the loop at all if the glob has an expansion, and the unconditional break statement ensures that the gzip command will only be executed once. It's a bit funny because it uses a for loop as an if, but it ...


3

Maybe this would do the trick for you ? while True; do python MyApp.py || echo "App crashed... restarting..." >&2 echo "Press Ctrl-C to quit." && sleep 1 done


3

One practical example would be in a shell script which will run up to a certain point, and then suspend itself with further tasks lined up for when the script is resumed by sending it a SIGCONT signal. By way of a for-instance: #!/bin/bash curl -o ./myfile http://source.example.com/path/to/important/file echo "Okay, now edit myfile to reflect the changes ...


2

Use uploading instead, via SSH from your local machine A "minimal headless *nix" box means you probably SSH into it. So you can also use SSH to upload to it. Which is functionally equivalent to downloading (of software packages etc.) except when you want a download command to include in a script on your headless server of course. As shown in this answer, ...


2

Functions defined in .bash_profile are only available in the shell that reads .bash_profile and not available in sub shells. When you open a terminal window you may be opening a non login shell. Some terminal programs may let you open a login shell (eg gnome-terminal has it at edit -> profile preferences). However if you shell out of another program (eg ...



Only top voted, non community-wiki answers of a minimum length are eligible