Difference between revisions of "Bash/scripts"
From Christoph's Personal Wiki
(→Functions) |
(→Run a local script on a remote host) |
||
Line 123: | Line 123: | ||
$ ssh user@remotehost 'bash -s' < script.sh | $ ssh user@remotehost 'bash -s' < script.sh | ||
$ ssh user@remotehost 'bash -s' <<'EOS' | $ ssh user@remotehost 'bash -s' <<'EOS' | ||
− | + | # The following commands will be run on the remote host | |
− | + | pwd | |
− | + | touch foobar | |
− | + | uptime | |
− | + | EOS | |
The <code>bash -s</code> command means: execute the following commands in a new bash session. The <code>-s</code> flag makes it read from standard input. | The <code>bash -s</code> command means: execute the following commands in a new bash session. The <code>-s</code> flag makes it read from standard input. |
Latest revision as of 22:38, 21 September 2021
See the bash man page for detailed explanations.
Contents
History functions
history # display history for current tty !! # repeat last command !foo # repeat last command starting with 'foo' !N # execute command number N from history output !foo:p # _show_ last command starting with 'foo' but do _not_ execute it !-N$:p # _show_ N-commands ago but do _not_ execute it !$ # grab last argument from previous command !* # grab all arguments from previous command ^F^f # change first instance of "F" to "f" in last command (i.e., ^error^correction)
Command movements
Note: The carret ^
symbols means Ctrl+
.
^w # erase word under cursor ^u # erase from here to beginning of the line ^a # move the cursor to the beginning of the line ^e # move the cursor to the end of the line
Brace expansion
Instead of doing this:
cp filename filename-old cp filename-old filename
Try this:
cp filename{,-old} cp filename{-old,}
- Create multiple files
touch a{1,2,3}b # creates 'a1b', 'a2b', and 'a3b' touch {f1,f2,f3,}o # creates 'f1o', 'f2o', 'f3o', and 'o'
- List the files '
/usr/bin/foo
', '/usr/sbin/foo
', '/usr/local/bin/foo
', and '/usr/local/sbin/foo
':
ls /usr/{,local/}{,s}bin/foo
- Sequences
echo {1..3}{foo,bar} # prints '1foo 1bar 2foo 2bar 3foo 3bar'
- Make a backup (not super useful, but nifty)
cp my.cnf{,.bak} # i.e., 'cp my.cnf my.cnf.bak' # to restore the original cp my.cnf{.bak,} # i.e., 'cp my.cnf.bak my.cnf'
- Etc.
mkdir /usr/local/src/bash/{old,new,dist,bugs} chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}} for i in {a..z}{1..9}; do echo $i; done # might not work in all shells
Word modifiers
h # remove a trailing file name component, leaving only the head. t # remove all leading file name components, leaving the tail. r # remove a trailing suffix of the form .xxx, leaving the basename. e # remove all but the trailing suffix.
- First list a file, then cd into its directory
ls -l foo/bar.txt cd !$:h # changes pwd to 'foo'
- Create a file and a directory as the basename of the file
touch foo.txt mkdir !$:r # creates a directory called 'foo' (without the .txt)
- Stacked word modifiers: Download a file to
/tmp
, and then create a directory for the contents of that tar file in/usr/local/src
. Then extract the contents of the tarball into the newly created directory:
cd /tmp wget http://www.example.com/path/SomePackageName.tar.gz cd /usr/local/src/ mkdir !-2$:t:r:r # creates a directory called 'SomePackageName' cd !$ # enter the above directory tar xvzf /tmp/!-4$:t # extract the contents of 'SomePackageName.tar.gz' here
- Substitution:
ls Foo # file/directory does not exist, so: !!:s/Foo/foo/ # change 'Foo' to 'foo' in last command
- Substitution (global):
ls Foo1; ls Foo2 # neither file/directory exist, so: !!:gs/F/f/ # replace all 'F' with 'f' in previous command
Functions
"$0" # name of command/function "$1" # 1st argument "$2" # 2nd argument "${*}" # all arguments "${#}" # total _number_ of arguments
- Create a function to ls a given file (as an argument). A silly but simple example:
function myfoo { ls -l "${1}"; }; myfoo bar.txt # same as 'ls -l bar.txt'
- Copy everything in
/foo
, to the directory/bar
preserving permissions and ownership (see: tar):
function treecp { (cd "${1}"; tar -cf - . ) | (cd "${2}"; tar --same-owner -xpf - )
- Using
"${*}"
:
function myargs { echo "${*}" >>foo; }; myargs one two three # concatenates "one two three" into 'foo'
- Using
"${#}"
:
function myfunc { echo "${#}" ; } ; myfunc foo bar # returns "2" myfunc * # output is the same as 'ls | wc -l' myfunc # returns "0"
- Exception handling (using the previous
treecp
function):
function treecp { if [ "${#}" != 2 ] ; then echo "Usage: treecp source destination"; return 1; else tar cf - "${1}" | (cd "${2}" ; tar xpf -) ; fi ; };
- Error handling:
function err { grep "${*}" /usr/include/*/errno.h; if [ "${?}" != 0 ] ; then echo "Not found." fi };
Run a local script on a remote host
$ ssh user@remotehost 'bash -s' < script.sh $ ssh user@remotehost 'bash -s' <<'EOS' # The following commands will be run on the remote host pwd touch foobar uptime EOS
The bash -s
command means: execute the following commands in a new bash session. The -s
flag makes it read from standard input.