This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
fuss:sh [2020/03/30 05:18] – [For ZIP] office | fuss:sh [2025/06/10 03:18] (current) – [Replace Text in Files using Perl] office | ||
---|---|---|---|
Line 14: | Line 14: | ||
<code bash> | <code bash> | ||
########################################################################### | ########################################################################### | ||
- | ## Copyright (C) Wizardry and Steamworks | + | ## Copyright (C) Wizardry and Steamworks |
- | ## Please see: http://www.gnu.org/licenses/gpl.html | + | ## Please see: https://opensource.org/license/mit/ for legal details, |
## rights of fair usage, the disclaimer and warranty conditions. | ## rights of fair usage, the disclaimer and warranty conditions. | ||
########################################################################### | ########################################################################### | ||
Line 165: | Line 165: | ||
====== Lock ====== | ====== Lock ====== | ||
- | To prevent parallel execution of scripts, the following snippet can be used: | + | To prevent parallel execution of scripts, the following snippet can be placed within existing scripts at any point where the operations following the snippet must be guaranteed to be executed by a single script: |
<code bash> | <code bash> | ||
# Acquire a lock. | # Acquire a lock. | ||
LOCK_FILE='/ | LOCK_FILE='/ | ||
- | if mkdir $LOCK_FILE | + | if mkdir "$LOCK_FILE" |
- | trap '{ rm -rf $LOCK_FILE; }' | + | trap '{ rm -rf $LOCK_FILE; }' |
else | else | ||
exit 0 | exit 0 | ||
Line 180: | Line 180: | ||
* '' | * '' | ||
- | The command '' | + | The command '' |
- | The snippet can be used directly in any script just by setting the value of '' | + | The snippet can be used directly in any script just by setting the value of '' |
====== Loop Over Command Line Arguments ====== | ====== Loop Over Command Line Arguments ====== | ||
Line 279: | Line 279: | ||
</ | </ | ||
which will take the last command and arguments and place them in a file called '' | which will take the last command and arguments and place them in a file called '' | ||
- | ====== Pipe Visualiser | + | |
+ | ====== Pipe Visualizer | ||
'' | '' | ||
Line 516: | Line 517: | ||
</ | </ | ||
- | ====== Replace | + | ====== Replace |
- | To replace a string in multiple files you can use '' | + | ^ Command Line Aspect ^ Visual Mnemonic Graft ^ |
+ | | '' | ||
<code bash> | <code bash> | ||
- | find . -type f -exec perl -p -i -e ' | + | perl -p -i"" |
+ | </ | ||
+ | where: | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | * '' | ||
+ | |||
+ | The former can also be combined with '' | ||
+ | <code bash> | ||
+ | find . -type f -exec perl -p -i'' | ||
</ | </ | ||
this command will search all files in the path and replace the string '' | this command will search all files in the path and replace the string '' | ||
+ | ====== Print Match Groups with Perl ====== | ||
+ | |||
+ | One of the advantages of using Perl is that it is integrated with most operating systems and also by default uses regular expressions. | ||
+ | |||
+ | Using grep is not that useful given that in spite of benefiting from regular expressions via the POSIX flag '' | ||
+ | |||
+ | For instance, the following command: | ||
+ | <code bash> | ||
+ | ffmpeg \ | ||
+ | -i a.mp4 \ | ||
+ | -filter_complex ebur128=peak=true \ | ||
+ | -f null - 2>&1 | \ | ||
+ | tr -s ' ' | \ | ||
+ | grep FTPK | \ | ||
+ | perl -ne '/t: ([0-9\.]+).+? | ||
+ | </ | ||
+ | will extract the time stamp and the noise peaks from an input file '' | ||
+ | |||
+ | The input that the perl command processes is the following: | ||
+ | < | ||
+ | [Parsed_ebur128_0 @ 00000000041e8c00] t: 28.5695 TARGET:-23 LUFS M: -55.3 S: -57.4 I: -33.2 LUFS LRA: 18.8 LU FTPK: -48.7 -48.7 dBFS TPK: -5.9 -5.9 dBFS | ||
+ | </ | ||
+ | |||
+ | Using Perl also has the advantage that the output can be customized, via the '' | ||
+ | <code bash> | ||
+ | perl -ne '/t: ([0-9\.]+).+? | ||
+ | </ | ||
+ | After that the first and second match group are printed out and a newline appended. Fortunately the '' | ||
====== Transfer a Directory between Servers ====== | ====== Transfer a Directory between Servers ====== | ||
This can be performed in several ways depending on the tools available. | This can be performed in several ways depending on the tools available. | ||
- | ===== Using Tape Archives ===== | + | ===== Using Tape Archives |
This can be accomplished by using '' | This can be accomplished by using '' | ||
Line 807: | Line 849: | ||
* '' | * '' | ||
* '' | * '' | ||
+ | |||
+ | ====== Find Plaintext Files ====== | ||
+ | |||
+ | <code bash> | ||
+ | find . -type f -exec grep -Iq . {} \; -print | ||
+ | </ | ||
+ | |||
+ | ====== Ensure Newline at End of File ====== | ||
+ | |||
+ | <code bash> | ||
+ | find -name \*.txt | while read f; do tail -n1 $f | read -r _ || echo >> $f; done | ||
+ | </ | ||
+ | where: | ||
+ | * '' | ||
+ | |||
+ | ====== Execute Script as a Different User ====== | ||
+ | |||
+ | Using '' | ||
+ | |||
+ | <code bash> | ||
+ | # Restart the script as an user via su. | ||
+ | if [ "$(id -u)" -eq 0 ]; then | ||
+ | # exec replaces current shell | ||
+ | exec su myanonamouse " | ||
+ | # this line will not be reached | ||
+ | fi | ||
+ | |||
+ | # this will run as user " | ||
+ | </ | ||
+ | |||
+ | ====== Get External IP Address via DNS ====== | ||
+ | |||
+ | Using '' | ||
+ | |||
+ | <code bash> | ||
+ | dig +short myip.opendns.com @resolver1.opendns.com | ||
+ | </ | ||
+ | |||
+ | ====== Create a File under a Given Username and Group at Once ====== | ||
+ | |||
+ | The following command: | ||
+ | <code bash> | ||
+ | install -D -o www-data -g www-data /dev/null / | ||
+ | </ | ||
+ | will create the file ''/ | ||
+ | |||
+ | ====== Print a Character a Certain Number of Times ====== | ||
+ | |||
+ | The following line will print 10 successive dots: | ||
+ | <code bash> | ||
+ | yes " | ||
+ | </ | ||
+ | |||
+ | ====== Using the Results Placeholder for the find Utility ====== | ||
+ | |||
+ | The Unix utility '' | ||
+ | <code bash> | ||
+ | find . -type f -name ' | ||
+ | </ | ||
+ | such that the command after the '' | ||
+ | |||
+ | Remarkably, as feature-packed as Unix tools are, the results placeholder is deceptively straightforward and without features. For example, one of the most common tasks is to perform some sort of string substitution on the results in case the file must be moved or manipulated in any way. | ||
+ | |||
+ | In order to use the file name without further bothering about the '' | ||
+ | <code bash> | ||
+ | find . -type f -name ' | ||
+ | </ | ||
+ | |||
+ | Whilst the command invocation: | ||
+ | <code bash> | ||
+ | find . -type f -name ' | ||
+ | </ | ||
+ | is responsible for finding files ending with the '' | ||
+ | < | ||
+ | bash -c 'mv " | ||
+ | + | ||
+ | | | ||
+ | +-----+ | ||
+ | execute a | | | ||
+ | command | ||
+ | | ||
+ | | ||
+ | | | ||
+ | | | ||
+ | | $0 is the first parameter | ||
+ | | passed to bash and holds | ||
+ | | the exact contents of {} | ||
+ | </ | ||
+ | |||
+ | Something that seems counter-intuitive is that the command passed to the bash '' | ||
+ | <code bash> | ||
+ | find . -type f -name ' | ||
+ | </ | ||
+ | |||
+ | Interestingly, | ||
+ | <code bash> | ||
+ | .................................. bash -c "mv \" | ||
+ | </ | ||
+ | then the command would not run properly because while issuing the " | ||
+ | <code bash> | ||
+ | .................................. bash -c 'mv " | ||
+ | </ | ||
+ | such that substitution only occurs when the command passed to the '' | ||
+ | |||
+ | ====== Shell alarm(2) Implementation ====== | ||
+ | |||
+ | An equivalent to the '' | ||
+ | |||
+ | <code bash> | ||
+ | # alarm(2) | ||
+ | function alarm { | ||
+ | sleep $1 | ||
+ | # this is the command to be executed after the elapsed time | ||
+ | echo " | ||
+ | } | ||
+ | |||
+ | |||
+ | # ensures that any pending alarm is cleared upon termination of the current script | ||
+ | ALARM_PID=0 | ||
+ | trap '{ test $ALARM_PID = 0 || kill -KILL $ALARM_PID; }' KILL QUIT TERM EXIT INT HUP | ||
+ | |||
+ | # the parent program consists in a process that runs indefinitely | ||
+ | while " | ||
+ | # when the alarm must be re-armed: | ||
+ | # * kill the previous alarm | ||
+ | # * reschedule the alarm into the future | ||
+ | if [ -d / | ||
+ | kill -9 $ALARM_PID | ||
+ | fi | ||
+ | alarm " | ||
+ | ALARM_PID=$! | ||
+ | done | ||
+ | |||
+ | </ | ||
+ | |||
+ | The actual code to be executed is to be found within the '' | ||
+ | |||
+ | Note that the expression '' | ||
+ | |||
+ | ====== Comparing Files Line-by-Line ====== | ||
+ | |||
+ | Given two files '' | ||
+ | |||
+ | ===== Lines in A but not in B ===== | ||
+ | |||
+ | "Lines in file A but not in file B" is a set subtraction $A \setminus B$ (defined as all elements / lines in $A$ that are not in $B$). | ||
+ | |||
+ | $$ | ||
+ | \begin{venndiagram2sets} | ||
+ | \fillANotB | ||
+ | \end{venndiagram2sets} | ||
+ | $$ | ||
+ | |||
+ | To perform this operation, issue: | ||
+ | <code bash> | ||
+ | comm -23 <(sort A) <(sort B) | ||
+ | </ | ||
+ | |||
+ | ===== Lines in B but not in A ===== | ||
+ | |||
+ | "Lines in file B but not in file A" is a set subtraction $B \setminus A$ (defined as all elements / lines in $B$ that are not in $A$). | ||
+ | |||
+ | $$ | ||
+ | \begin{venndiagram2sets} | ||
+ | \fillBNotA | ||
+ | \end{venndiagram2sets} | ||
+ | $$ | ||
+ | |||
+ | To perform this operation, issue: | ||
+ | <code bash> | ||
+ | comm -13 <(sort A) <(sort B) | ||
+ | </ | ||
+ | |||
+ | ===== Lines Common to Both A and B ===== | ||
+ | |||
+ | "Lines in file A that are also in B" is a set intersection $A \cap B$. | ||
+ | |||
+ | $$ | ||
+ | \begin{venndiagram2sets} | ||
+ | \fillACapB | ||
+ | \end{venndiagram2sets} | ||
+ | $$ | ||
+ | |||
+ | To perform this operation, issue: | ||
+ | <code bash> | ||
+ | comm -12 <(sort A) <(sort A) | ||
+ | </ | ||
+ | |||
+ | ====== Return Machine Utilization from Load Average ====== | ||
+ | |||
+ | On the [[/ | ||
+ | |||
+ | <code bash> | ||
+ | awk '{ print int(100 - $1/$NF) }' <<< | ||
+ | </ | ||
+ | |||
+ | Note that the CPU utilization is computed relative to the 5minute usage over time returned from ''/ | ||
+ | |||
For the contact, copyright, license, warranty and privacy terms for the usage of this website please see the contact, license, privacy, copyright.