Bash/scripts

From Christoph's Personal Wiki
Revision as of 22:38, 21 September 2021 by Christoph (Talk | contribs) (Run a local script on a remote host)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

See the bash man page for detailed explanations.

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.