Skip to content

Instantly share code, notes, and snippets.

@arnaudjuracek
Last active February 4, 2020 15:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arnaudjuracek/5b1e93310e4915a61bc31167ad178804 to your computer and use it in GitHub Desktop.
Save arnaudjuracek/5b1e93310e4915a61bc31167ad178804 to your computer and use it in GitHub Desktop.

bash snippets


Personnal collection of useful bash snippets.



Table of Contents



Basics

Repeat last command

!!

Repeat last argument

!$

alternatively, use ESC + .

Expand wildcards

CTRL + x, * will expand the last glob pattern:

$ rm *
# ctrl + x, *
$ rm fileA fileB fileC

Variable expansion

use double quotes to allow variable to expand (single quote won't interpolate anything):

$ echo '$(date +%Y-%m-%d_%H-%M)'
> $(date +%Y-%m-%d_%H-%M)

$ echo "$(date +%Y-%m-%d_%H-%M)"
> 2018-02-18_15-01

Array and list

mkdir {folderA,folderB,folderC}
touch file_{0..10}.txt

Loops

for c in {H,E,L,L,O}; do echo $c; done
for i in {1..10}; do echo $i; done
for f in *.png; do echo $f; done

use ${f%%.*} to print filename without extension:

for f in *.png; do echo ${f%%.*}; done

Sequential vs parallel loop execution

ecco () { sleep 1; echo $1; }

# sequential
for i in {0..10}; do ecco $i; done

# parallel
for i in {0..10}; do ecco $i & done; wait


File manipulation

Append timestamp

touch $(date +%Y-%m-%d_%H-%M).log

Lowercase a batch of files

for f in *; do mv "$f" "$f.tmp"; mv "$f.tmp" "`echo $f | tr "[:upper:]" "[:lower:]"`"; done

Batch change file extension in any depth

for f in {,**/}*.txt; do mv $f "${f/%.txt/.fr.txt}"; done

Delete files under 1kB

# Running dry
find * -type f -size -1024c -exec echo '{}' \;
# Actually deleting files
find * -type f -size -1024c -exec rm '{}' \;

See --size in find(1)

Clean up SVGs and convert to php file

using svgo:

for f in *.svg; do svgo --input $f --pretty --enable={removeStyleElement,removeXMLNS,cleanupIDs}; mv $f ${f%%.*}.php; done

Pipe a list of paths to a command

cat files.txt | xargs $@ <COMMAND>


Media manipulation

Resize all .JPG wider than 1280px

using imagemagick/mogrify:

mogrify -quality 85 -resize '1280>' *.JPG

Change an image density

using imagemagick/density:

convert -units PixelsPerInch image-in-72-dpi.png -density 300 image-in-300-dpi.png

Histogram matching

using histmatch:

for i in {8143..8370}; do histmatch -c gray DSCF8142.JPG DSCF$i.JPG norm/$i.JPG; done

Make a timelapse from with all JPG in CWD

using ffmpeg:

ffmpeg -r 25 -pattern_type glob -i '*.JPG' -s hd1080 -vcodec libx264 timelapse.mp4

Extract a frame from a movie

using ffmpeg:

ffmpeg -i video.mp4 -ss 00:00:01.000 -vframes 1 cover.png


git related

Get LOC in src/*.js for each contributor

git ls-tree -r -z --name-only HEAD -- src/*.js | xargs -0 -n1 git blame --line-porcelain HEAD |grep  "^author "|sort|uniq -c|sort -nr

List modified and staged files

git diff --name-only --relative

use | xargs $@ <COMMAND> to run a command against this list:

git diff --name-only --relative | xargs $@ open

List modified and unstaged files

git ls-files -m --others --exclude-standard

use | xargs $@ <COMMAND> to run a command against this list:

git ls-files -m --others --exclude-standard | xargs $@ open

List modified files since...

# ... last commit
git diff --name-only HEAD HEAD~1 | cat

# ... latest release
git diff --name-only HEAD $(git describe --abbrev=0 --tags) | cat

# ... previous release
git diff --name-only HEAD $(git describe --abbrev=0 --tags `git rev-list --tags --skip=1 --max-count=1`) | cat

Reset working changes to latest origin

using current_branch from oh-my-zsh:

git reset --hard origin/$(current_branch)

Update feature branch from master prior to PR

git checkout feature
git fetch origin
git rebase origin/master
@arnaudjuracek
Copy link
Author

In addition, see jlevy's the-art-of-command-line.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment