Shell Scripting

Let's have one of these again.

ITT:
- post OC sh/ksh/bash scripts and one-liners
- spread POSIX, UUOC and etc. autism
- also welcome: sed and awk wizards

NOT ITT:
- zsh hipsters
- fish cripples
- powershell cucks

Other urls found in this thread:

github.com/fish-shell/fish-shell/wiki/POSIX-compatibility-thoughts
wiki.bash-hackers.org/commands/classictest
github.com/blyxxyz/remotely
blog.z3bra.org/2014/01/images-in-terminal.html
gnu.org/fun/jokes/ed-msg.txt
download.owncloud.org/community/owncloud-9.0.2.tar.bz2
perl.com/doc/FMTEYEWTK/versus/csh.whynot
my.mixtape.moe/cxfbog.insults
whatcolourisit.scn9a.org/
downloads.tuxfamily.org/godotengine/
youtube.com/watch?v=dNw4PwVYzSs
transparenttextures.com
transparenttextures.com/
transparenttextures.com/\1|p'
github.com/Keith-S-Thompson/random-passwords.git
github.com/koalaman/shellcheck.
github.com/scrooloose/syntastic).
youtube.com/user/DonaldTrumpVEVO
gnu.org/licenses/>.
pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
github.com/Kagami/webm.py
zsh.sourceforge.net/Doc/Release/Functions.html
pubs.opengroup.org/onlinepubs/9699919799/
en.wikipedia.org/wiki/Langton's_ant
dyne.org/software/tomb/
42xlyaqlurifvvtq.onion/endware/
42xlyaqlurifvvtq.onion
endchan5doxvprs5.onion/os/
tldp.org/LDP/abs/html/
wiki.ubuntu.com/DashAsBinSh
spit.mixtape.moe/view/9ee7a585
imagemagick.org/script/cipher.php
pubs.opengroup.org/onlinepubs/9699919799/utilities/date.html
bruxy.regnet.cz/web/linux/EN/matrix-sh/):
bruxy.regnet.cz/web/linux
gitgud.io/ring/infinityctl
media.8ch.net/tech/src/1472080974290.gif
media.8ch.net/file_store/bbb09c6811e48229599505ea136f6c6461ebf39c88924086fe0db022f0629228.jpg
twitter.com/NSFWRedditVideo

Kickin' the ball of with some functions.

mk7z(){ 7z a -t7z -m0=lzma -mx=9 -mfb=64 -md=32m -ms=on "${1%%/}.7z" "$1"}mktgz(){ GZIP=-9 tar cvzf "${1%%/}.tgz" "$1"}mktxz(){ XZ_OPT=-9 tar cvJf "${1%%/}.txz" "$1"}mkzip(){ zip -r "${1%%/}.zip" "$1"}
- highest compression
- file/glob/dir target

Stupid simple CI test runner; set it to watch your output executable and it'll run tests whenever you do a successful build

#!/bin/bashwhile ; do inotifywait --quiet --quiet --event close_write $1 sleep 0.2s; clear; make test;done

It's always a good idea to use #!/usr/bin/env bash instead of #!/bin/bash when you share scripts; some sytems don't have bash in /bin/ but env will search for it for you.

This woun't work without something like : or true, also why a loop at all?

Most of these semicolons are not needed in multiline scripts.

sleep 0.2s
clear
make test

should do the job.

From my bash.rc:
optimize() { for f in "$@"; do case "$f" in *gif) gifsicle -bO3 "$f" ;; *png) optipng -o 6 -strip all "$f" ;; *jpg) jpegoptim --strip-all "$f" ;; *) printf "Something happend.\n" return 1 ;; esac done}
Improvements/addons welcome.

fish master race

github.com/fish-shell/fish-shell/wiki/POSIX-compatibility-thoughts

Yeah I forgot while ; do only works in zsh
But... but I like my semicolons

nothing wrong with zsh

Created this just to keep track of all my projects.
#!/bin/bash# Checks current status of repositories within current directorybase=`pwd`IFS=$(echo -en "\n\b")for d in `find . -type d -name .git` ; do cd "$d/.." && printf "$(dirname "$d")/\n" git remote update && git status -sb cd $base && printf "\n"doneread -p "Press [Enter] key to close..."

shit like this is why i hate shell scripting

why the straight brackets? why the semicolon? why is it an error if you don't have a space between the [ and the "?

Because [ can be understood as a standalone program, therefore you must separe it from its arguments.

This:
[ is basically the same as the "test" program, just with a trailing ]. More infos:
wiki.bash-hackers.org/commands/classictest

It's not needed when you write it like this:
if [ "$rename" != "" ]then foofi
It just looks better to put things like ; then and ; do on the same line.

function mpc-add-random-album(){ 1=${1:-1} mpc list album | shuf | head -$1 | xargs -I{} mpc find album '{}' | mpc add}function sed-rename(){ for i in ${@:2} do mv "$i" "$(sed "$1"

This is actually noice.

table(){ awk 'BEGIN { for (i = 32; i < 128; i++) printf "%3d %o 0x%02x %c\n" ,i ,i, i, i }' | column -c 80}

$ table 32 40 0x20 52 64 0x34 4 72 110 0x48 H 92 134 0x5c \ 112 160 0x70 p 33 41 0x21 ! 53 65 0x35 5 73 111 0x49 I 93 135 0x5d ] 113 161 0x71 q 34 42 0x22 " 54 66 0x36 6 74 112 0x4a J 94 136 0x5e ^ 114 162 0x72 r 35 43 0x23 # 55 67 0x37 7 75 113 0x4b K 95 137 0x5f _ 115 163 0x73 s 36 44 0x24 $ 56 70 0x38 8 76 114 0x4c L 96 140 0x60 ` 116 164 0x74 t 37 45 0x25 % 57 71 0x39 9 77 115 0x4d M 97 141 0x61 a 117 165 0x75 u 38 46 0x26 & 58 72 0x3a : 78 116 0x4e N 98 142 0x62 b 118 166 0x76 v 39 47 0x27 ' 59 73 0x3b ; 79 117 0x4f O 99 143 0x63 c 119 167 0x77 w 40 50 0x28 ( 60 74 0x3c < 80 120 0x50 P 100 144 0x64 d 120 170 0x78 x 41 51 0x29 ) 61 75 0x3d = 81 121 0x51 Q 101 145 0x65 e 121 171 0x79 y 42 52 0x2a * 62 76 0x3e > 82 122 0x52 R 102 146 0x66 f 122 172 0x7a z 43 53 0x2b + 63 77 0x3f ? 83 123 0x53 S 103 147 0x67 g 123 173 0x7b { 44 54 0x2c , 64 100 0x40 @ 84 124 0x54 T 104 150 0x68 h 124 174 0x7c | 45 55 0x2d - 65 101 0x41 A 85 125 0x55 U 105 151 0x69 i 125 175 0x7d } 46 56 0x2e . 66 102 0x42 B 86 126 0x56 V 106 152 0x6a j 126 176 0x7e ~ 47 57 0x2f / 67 103 0x43 C 87 127 0x57 W 107 153 0x6b k 127 177 0x7f  48 60 0x30 0 68 104 0x44 D 88 130 0x58 X 108 154 0x6c l 49 61 0x31 1 69 105 0x45 E 89 131 0x59 Y 109 155 0x6d m 50 62 0x32 2 70 106 0x46 F 90 132 0x5a Z 110 156 0x6e n 51 63 0x33 3 71 107 0x47 G 91 133 0x5b [ 111 157 0x6f o$

num2led() { printf '%s\n' "$*" \ | sed \ ' h s/[14]/ /g s/[0-9]/ _ /g G s/0/| | /g y/24569/38228/ G s/[068]/|_| /g s/[147]/ | /g s/2/|_ /g s/[359]/ _| /g '}
Ex: num2led $(date +%H%M)

Just man ascii, m8.

You fucker

this is bangin, nice job

This script lets you use URLs as files:
github.com/blyxxyz/remotely
#!/bin/bashmain () { for arg in "${@:i+1}"; do if [[ "$arg" =~ ^[[:alpha:]][[:alnum:]+.-]*:// ]]; then main "${@:1:i}"

Casual here.
I put these in my .bashrc

lx () { lynx --dump "$@" | more; }
tw () { livestreamer twitch.tv/"$@" source; }

Am I cool Linux user now?

I like the -n switch of rename to preview changes. How to make something like this for rm?

The -i flag makes it prompt before every deletion.

Shows man page for command under cursor and lets you continue where you left off when you're done . Useful when you have a long command line and need to quickly look at some man page.function man_on_word { TMP_LN=$READLINE_LINE TMP_POS=$READLINE_POINT while [ $TMP_POS -gt 0 ] && [ "${TMP_LN:TMP_POS:1}" != " " ] do true $((--TMP_POS)) done if [ 0 -ne $TMP_POS ]; then true $((++TMP_POS));fi TMP_WORD="${READLINE_LINE:$TMP_POS}" TMP_WORD="${TMP_WORD%% *}" man "$TMP_WORD"}bind -x '"\C-k":man_on_word'#optionally:set -o vibind -m vi-command -x '"K":man_on_word'

"Thumbnails" a webm for Holla Forums by replacing the appropriate frames with your thumbnail.#!/bin/bashfunction usage() { echo "usage: $0 [options] " echo "options:" echo " -an indicates that does not contain audio" echo " -e reencoes the result in preset quality"}tmpdir=/tmp/thumbwebmdir-$$ffmpeg="ffmpeg -hide_banner"mkdir $tmpdir[ $# -lt 3 ] && usage "$0" && exit 1while [ $# -gt 3 ]; do case "$1" in -an) an=1;shift;break;; -e) e=1;shift;break;;esac;done[ $# -lt 3 ] && usage "$0" && exit 1file_in="$1"file_thumb="$2"file_out="$3"ffprobe_out=`ffprobe -v quiet -show_format -show_streams $file_in`width=`grep -E '^width=[0-9]+$'

Is it the fps that makes the thumbnail frame last so long? Usually I don't notice the thumbnail frame in videos.

Based. Thanks user. Saved both.

got this from the Arch wiki:
bind '"\eh": "\C-a\eb\ed\C-y\e#man \C-y\C-m\C-p\C-p\C-a\C-d\C-e"'

wim(){ w3m -o ext_image_viewer=off "$@"}
wim - w3m image viewer

blog.z3bra.org/2014/01/images-in-terminal.html

This line is terrifying.
read width height

why does bash have a logo now

There's a couple of packages which do enable image rendering in a tty, granted you can utilize the framebuffer.

Removed the first \C-a, so it does man for the word under the curser, not for the first word of the line. Did I do good? I have basically no idea what I'm doing here.
bind '"\em": "\eb\ed\C-y\e#man \C-y\C-m\C-p\C-p\C-a\C-d\C-e"'

# Read pdfs with less.vpdf(){ pdftotext -layout "$1" - | less -r}# Suckless nfo viewer.vnfo(){ iconv --from-code 437 --to-code UTF8 "$1" | less}

Replacing 1 frame didn't work reliably so I replace last frame from first part of video and first frame from 2nd part. It should probably be possible to figure out how to do it with just 1 frame, but I wasn't bothered enough to try doing that.

Random i3lock/ImageMagick faggotry incoming.

i3lock-blur(){ i3lock -ni /dev/null}i3lock-glitch(){ i3lock -ni /dev/null \ ) &>/dev/null}i3lock-grayscale(){ i3lock -ni /dev/null}i3lock-lossy(){ i3lock -ni /dev/null}i3lock-negate(){ i3lock -ni /dev/null}i3lock-pixelate(){ i3lock -ni /dev/null}i3lock-pixelate-logo(){ i3lock -ni /dev/null}

maybe it depends on whether there's an even or odd number of frames.

Thanks. I'll use these for my laptop. Could you make a screenshot of some of the effects?

...

alias vi="curl gnu.org/fun/jokes/ed-msg.txt && ed"

What do you think anons?
I made an ubuntu server with open SSH and pretty much just copy paste this into the fields then install the clients and it works

#!/bin/bash#made with Ubuntu 16.04 LTS#run as root first#sets a static IP for the server, make sure to change the IPs to match your needssed -i '$d' /etc/network/interfacescat /etc/network/interfacesiface enp0s3 inet staticaddress 192.168.1.77netmask 255.255.255.0gateway 192.168.1.1EOF#downloads nessicary software for the serverapt-get -y update && apt-get -y upgrade && apt-get -yV install apache2 mysql-server php7.0 php7.0-curl php7.0-gd php7.0-intl php-imagick php7.0-json php7.0-mcrypt php7.0-mysql php7.0-xml php7.0-zip libapache2-mod-php7.0#Downloads and installs the softwarecd ~ && wget download.owncloud.org/community/owncloud-9.0.2.tar.bz2 && tar vxjf owncloud-9.0.2.tar.bz2 && cp -r owncloud /var/www/html && cp -r owncloud /var/www/html && chown -R www-data:www-data /var/www/html/owncloud/#writes in and links together some important filestouch /etc/apache2/sites-available/owncloud.conf && ln -s /etc/apache2/sites-available/owncloud.conf /etc/apache2/sites-enabled/owncloud.conf && cat /etc/apache2/sites-available/owncloud.confServerAdmin [email protected] /var/www/html/owncloud/ServerName your-domain.comServerAlias www.your-domain.comOptions FollowSymLinksAllowOverride AllOrder allow,denyallow from allErrorLog /var/log/apache2/your-domain.com-error_logCustomLog /var/log/apache2/your-domain.com-access_log commonEOF#resets the server for testing to see if it is even upsystemctl restart apache2.service#End Manual Installation, you should be able to see the web client page now at [insert domain/IP here]/owncloud#Creat Database for owncloud#$ cd /var/www/html/owncloud/#$ sudo -u www-data php occ maintenance:install --database #"mysql" --database-name "owncloud" --database-user "root" --database-pass #"password" --admin-user "admin" --admin-pass "password"#ownCloud is not installed - only a limited number of commands are available#ownCloud was successfully installedcd /var/www/html/owncloud/ && sudo -u www-data php occ maintenance:install --database "mysql" --database-name "owncloud" --database-user "root" --database-pass "Carbon12.011" --admin-user "admin" --admin-pass "Carbon12.011"#the followign command allows access to the web client by accessign the IP domain, cannot be run before the database is createdsed -i "/ 0 => 'localhost',/a\\ 1 => '192.168.1.77'," /var/www/html/owncloud/config/config.phpsystemctl restart apache2.serviceclear; echo 'The server is now ready'; echo 'Type "192.168.1.77/owncloud" into your browser address bar to access the web app'; echo 'Then log in with the username and password'; echo 'now would be a good time to write them down'; echo ''; echo 'Username: admin'; echo 'Password: Carbon12.011'; echo ''; echo 'Press Enter to finish' ;read -n 1 -s

Oh, and it installs owncloud server software, the purpose is my own personal in house cloud so I can just connect my laptop to my wi-fi and it will sync my projects with my other computers

I just stick my shortcuts as separate files in ~/bin, am I doing it wrong?
Anyway, script to search current directory and return files and directories matching input:#!/usr/bin/env shls | grep $1
It's called 'f', so all I need to do is 'f x' to find x in the current directory.

neat

You should almost always quote a variable, by using "$1" instead of $1. That way it's treated as a single argument, the way you'd expect it to. If you don't quote it weird things can happen if it includes spaces or asterisks.

You can do this recursively using find.find -name "*$1*"
Do you know how to define shell functions? You can use them to put simple things like this in your .bashrc (or similar) instead of making whole files for them.
f () { ls | grep "$1"}

Thanks for the quoting tip, that sounds pretty useful.
I'll look into functions. They sound a lot easier than maintaining a folder of scripts.

Check $(file -

Bash scripting if fraught with peril. If you don't want to fuck it up do this:

set -xeu -o pipefail

The -x is optional but you'll want it during development. Trust me, I've fucked enough shit up to have learnt this the hard way.

Also, you don't want these options in .bashrc, but if you want a dangerous function to be safer you can make it spawn a subshell like this:

dangerous_function (){( set -xeu -o pipefail rm -rf /home/faggot/"$1")}

I got this from a shell scripting thread several months ago. Put it in .bashrc:
#Give the user a random insult if a command returns with an errortrap "curl -m 1 -s randominsults.net | sed -n '//{s;^.*\(.*\).*$;\1;p}'" ERR

Wh-what about (t)csh?

Enlightening

What it do

Why would you do $(file -

Considered harmful.
perl.com/doc/FMTEYEWTK/versus/csh.whynot

This is only really useful with a good internet connection. Try downloading this file to ~/.insults:
my.mixtape.moe/cxfbog.insults
It's sudo's list of insults, taken from /usr/lib/sudo/sudoers.so.

Then you can use:
trap 'shuf -n 1 ~/.insults' ERR

wasn't expecting any reply, but thank you so much for improving the script

I'd recommend against most of those options.
"set -e" is difficult to predict (especially when you introduce non-trivial pipes) and gives the false impression that you can be lax with error handling. There's a bunch of pages (e.g. wooledge's wiki) recommending against it.

As for "set -u", that's slightly more sensible but still unnecessary. Use the ? substitution if you want that behavior.

"set -o pipefail" is nice in theory but means you can't write a POSIX compatible shell script. Even then, if you're writing a bash script, you already have the pipe exit codes in PIPESTATUS so it's not really necessary.

tl;dr I think "set -e" and friends are lazy and encourage sloppy scripting, while also not being predictable enough to make for safe code

No particular reason in this case, just that doing it with a redirection tends to work with more commands and so it's become a habit. I used to do it a lot with the md5sum/sha512sum/etc commands.
For unusual filenames, it tends to give unusual output (backslash at the start of the hash; filename mangled in an undocumented way), so using this trick in that case avoids the need to parse that away (and might avoid the need for any parsing at all on the output).

It suggests that there's a reason for the redirection, because it's a (slightly) more complex and less obvious way to do it.

I suspected that printing the filename was a problem. The "-b" flag takes care of that.

That's the one. But as I said, it's just that I'm used to having to take this approach for other utilities.

How to do this in bash/sh?

wave() {lua -e 'local clock = os.clockfunction sleep(n) -- seconds local t0 = clock() while clock() - t0

Forgot to impeach tar from leaking username. Pretty important. Well, not really, since I almost always use lrzip and xz.
function xztar(){ tar -c -f - --numeric-owner -- "$1" | xz -v -T 0 -f - > "$1".tar.xz}

The script below is POSIX sh with all kinds of performance hacks that end up not being necessary due to the sleep. I didn't do the obvious sine table because it makes it lose precision much faster than I'd like (due to the weird step of 0.1 radians per line), and it would make the output differ from the original lua script in the first 100 lines.
#!/bin/sh# Magic to make unquoted variables behave differently# because dash's parser is ever so slightly faster with unquoted varsset -fIFS=frac_scale=100000pi=314159sine_iters=5 # Tuned to be "just accurate enough"sine() { # Designed to be used without a subshell acc=0 fact=1 xpow=$1 i=0 while [ $((i < sine_iters)) = 1 ]; do : $((acc += xpow / fact)) \ $((i += 1)) \ $((fact *= -2*i * (2*i + 1))) \ $((xpow = xpow * $1 / frac_scale * $1 / frac_scale)) done sine=$acc}wave_str='***** +++ 'wave_pos=0while true; do sine $wave_pos spaces=$((20 * (frac_scale + sine) / frac_scale)) printf '\n%*s%s' $spaces '' $wave_str wave_str_end=${wave_str#?} wave_str=$wave_str_end${wave_str%"$wave_str_end"} : $((wave_pos = (wave_pos + frac_scale/10))) \ $((wave_pos -= wave_pos > pi ? pi*2 : 0)) sleep 0.025done

Modified with a little more focus on readability than the above (...relatively speaking), bash only:
#!/bin/bashdec_1=100000 # The value of 1 in our "decimal" variablespi=314159 # pi (scaled by dec_1)sine_iters=5 # Accuracy of the sine function. No real "units" to this, configure it experimentally.sine() { local acc=0 fact=1 x=$1 xpow=$1 i=0 while ((i < sine_iters)); do ((acc += xpow / fact, i++, fact *= -2*i * (2*i + 1), xpow = xpow * x / dec_1 * x / dec_1 )) done echo "$acc"}wave_str='***** +++ 'wave_pos=0while true; do # Scale up from our sine wave (-1..1 dec) to 0..40 spaces=$((20 * (dec_1 + $(sine "$wave_pos")) / dec_1)) printf '\n%*s%s' "$spaces" '' "$wave_str" wave_str=${wave_str:1}${wave_str:0:1} ((wave_pos = (wave_pos + dec_1/10))) # Wrap wave_pos around if it reaches pi # Avoids the usual problem with Taylor series approximations (lower accuracy for higher magnitudes of x) if ((wave_pos > pi)); then ((wave_pos -= pi * 2)) fi sleep 0.025done

Yes I'm the same guy who wrote that shell script mandelbrot all those bash threads ago :^)

If you're wondering why so much of this looks like arcane nonsense, it's because bash and sh don't support floating point arithmetic (nor do they have a sine function), so I've had to hack around that.

If you'd allow external programs and sine tables, you can get this a lot more sensible looking:
#!/bin/bashwave_str='***** +++ 'wave_pos=0wave_pos_table=( $(perl -MMath::Trig -le 'print int((sin($_ * 0.1) + 1) * 20) for 0..62'))while true; do spaces=${wave_pos_table[wave_pos]} printf '\n%*s%s' "$spaces" '' "$wave_str" wave_str=${wave_str:1}${wave_str:0:1} wave_pos=$(((wave_pos + 1) % ${#wave_pos_table[@]})) sleep 0.025done
But of course every time it loops back to the start of the sine table*, it will lose precision. That means that unlike in the original lua script, the wave will repeat the same 63 lines over and over.
* position table, really, because I thought it would be faster to do all the other multiplications and such when the table is calculated.

You could invoke an external program to do the sine calculation every time, but that's slow enough that you can drop the sleep and you probably wouldn't notice(!)

Note that I've preserved all the "bugs" (IMO) of the lua script, like printing a blank line at the beginning and never reaching the leftmost column of the terminal.

Forgot to mention the most important point of that post: while this is all possible in bash, if you do need floating point arithmetic you should seriously consider a different lanugage.

Jesus christ. I'll need some time to let all this wizardry sink in. Thanks buddy. HQ post.

hex2rgb() { printf '%d %d %d\n' "0x${1:0:2}" "0x${1:2:2}" "0x${1:4:2}"}rgb2hex() { printf '%02X%02X%02X\n' "$1" "$2" "$3"}

One of the most useless pieces of code in my collection. Inspired by whatcolourisit.scn9a.org/
while :; do tput clear tput civis tput cup $(($(tput lines)/2)) $((($(tput cols)/2)-4)) d=$(date +%H%M%S) printf "\033]11;#$d\a#$d" read -s -n 1 -t 1 && exit done

Fair points, but you'll have to prise set -u from my cold dead fingers.

what do you think Holla Forums?
#!/bin/bash#Opens a new terminal and runs the sript#creates the .godot directory so that we don't have to wait for it to run to move the executable into it after it runs the first time#changes directory to ~/.godot so that it does not download to dropbox folder#displays current directory#downloads the file download version directory page into a text file and displays the portion with the version 2 download links#requests input of which version you would like to download#downloads the godot engine zip archive using $the version variable#unzips the godot engine executable to the .godot folder#moves the .zip archive file and the text file with vesion links to the trash to reduce clutter but allow you to keep the files if you want it#creates a Hard Symbolic link to your in home cloud storage directory where you keep fonts and things#notifies the user that the script is done#makes the script wait for a keypress before closing[ $# = 0 ] && exec gnome-terminal -e "bash -- '${0//\'/\'\\\\\'\'}' --no-term"mkdir ~/.godotcd ~/.godot || exitpwdwget -O delete_me.txt downloads.tuxfamily.org/godotengine/ && cat delete_me.txt | grep 'href="2'echo -e '\nAbove is a directory list of the curent versions of the godot engine'echo 'Please enter the version number you would like to download,'echo -n 'then press [ENTER](ex. "2.0.2": '; read version; echo $versionwget downloads.tuxfamily.org/godotengine/$version/Godot_v"$version"_stable_x11.64.zipunzip Godot_v"$version"_stable_x11.64.zip -d ~/.godot/gvfs-trash Godot_v"$version"_stable_x11.64.zipgvfs-trash delete_me.txtln -s /home/mint1/ownCloud-user/godot_files/godot_assets ~/.godot/godot_assetsecho -e '\nrun script complete\nPress ENTER to close this window'read -n 1 -s

actually here is a better one that doesn't wast time downloading the file if it's already there and it doesn't extract if the file is already extracted

#!/bin/bash#Opens a new terminal and runs the sript#creates the .godot directory so that we don't have to wait for it to run to move the executable into it after it runs the first time#changes directory to ~/.godot so that it does not download to dropbox folder#displays current directory#downloads the file download version directory page into a text file and displays the portion with the version 2 download links#requests input of which version you would like to download#downloads the godot engine zip archive using $the version variable if it is not already in the directory#unzips the godot engine executable to the .godot folder if it is not already there#moves the text file with vesion links to the trash to reduce clutter but allow you to keep the file if you want it#creates a Hard Symbolic link to your in home cloud storage directory where you keep fonts and things if a hard link does not already exist#notifies the user that the script is done#makes the script wait for a keypress before closing[ $# = 0 ] && exec gnome-terminal -e "bash -- '${0//\'/\'\\\\\'\'}' --no-term"mkdir ~/.godotcd ~/.godot || exitpwdwget -O delete_me.txt downloads.tuxfamily.org/godotengine/ && cat delete_me.txt | grep 'href="2'echo -e '\nAbove is a directory list of the curent versions of the godot engine'echo 'Please enter the version number you would like to download,'echo -n 'then press [ENTER](ex. "2.0.2"): '; read version; echo $versionwget -nc downloads.tuxfamily.org/godotengine/$version/Godot_v"$version"_stable_x11.64.zipunzip -n Godot_v"$version"_stable_x11.64.zip -d ~/.godot/gvfs-trash delete_me.txtln -s /home/mint1/ownCloud-anongodot_files/godot_assets ~/.godot/godot_assetsecho -e '\nrun script complete\nPress ENTER to close this window'read -n 1 -s

well I just realized how shit they are since they make infinite loops

[ $# = 0 ] && exec gnome-terminal -e "bash -- '${0//\'/\'\\\\\'\'}' --no-term"mkdir ~/.godotcd ~/.godot || exitln -sT ~/ownCloud-user/godot_files/godot_engine_assets ~/.godot/engine_assetsln -sT ~/ownCloud-user/godot_files/godot_engine_installers ~/.godot/engine_installersln -sT ~/ownCloud-user/godot_files/godot_project_exports ~/.godot/project_exportsln -sT ~/ownCloud-user/godot_files/godot_project_source ~/.godot/project_sourcecp -n ~/ownCloud-user/godot_files/godoticon.png ~/.godotpwdwget -O delete_me.txt downloads.tuxfamily.org/godotengine/ && cat delete_me.txt | grep 'href="2'echo -e '\nAbove is a directory list of the curent versions of the godot engine'echo 'Please enter the version number you would like to download,'echo -n 'then press [ENTER](ex. "2.0.2"): '; read version; echo $versionwget -nc -O ~/.godot/engine_installers/Godot_v"$version"_stable_x11.64.zip downloads.tuxfamily.org/godotengine/$version/Godot_v"$version"_stable_x11.64.zip unzip -n ~/.godot/engine_installers/Godot_v"$version"_stable_x11.64.zip -d ~/.godot/gvfs-trash delete_me.txtecho -e '\nrun script complete\nPress ENTER to close this window'read -n 1 -s

What it the best, correct and most portable escape sequence; \033, \x1b or \e? I just want to do it right.

\033 when used with printf. I suspect \x1b too but I've never actually confirmed that.
If you're using echo, you've lost already.

Fuck you Holla Forums

you said linux was more customizable

that I had the freedom to modify it how I please

Well you fucking lied to me

godot doesn't work right with symbolic links and apparently

HARD LINKS AREN'T ALLOWED

I spent 2 hours looking all over for a wy to bypass hard links restriction

I even checked the arch linux forum and even those faggots were like "soft links are good enough"

fucking chirst here is my new script until I finish the automation for adding mounts to /etc/fstab

#!/bin/bash[ $# = 0 ] && exec gnome-terminal -e "bash -- '${0//\'/\'\\\\\'\'}' --no-term"mkdir ~/.godotcd ~/.godot || exitmkdir ~/.godot/engine_assetsmkdir ~/.godot/engine_installersmkdir ~/.godot/project_exportsmkdir ~/.godot/project_sourcesudo umount ~/.godot/engine_assetssudo umount ~/.godot/engine_installerssudo umount ~/.godot/project_exportssudo umount ~/.godot/project_sourcesudo mount --bind ~/ownCloud-user/godot_files/godot_engine_assets ~/.godot/engine_assetssudo mount --bind ~/ownCloud-user/godot_files/godot_engine_installers ~/.godot/engine_installerssudo mount --bind ~/ownCloud-user/godot_files/godot_project_exports ~/.godot/project_exportssudo mount --bind ~/ownCloud-user/godot_files/godot_project_source ~/.godot/project_sourcecp -n ~/ownCloud-user/godot_files/godoticon.png ~/.godotpwdlswget -O delete_me.txt downloads.tuxfamily.org/godotengine/ && cat delete_me.txt | grep 'href="2'echo -e '\nAbove is a directory list of the curent versions of the godot engine'echo 'Please enter the version number you would like to download,'echo -n 'then press [ENTER](ex. "2.0.2"): '; read version; echo $versionwget -nc -O ~/.godot/engine_installers/Godot_v"$version"_stable_x11.64.zip downloads.tuxfamily.org/godotengine/$version/Godot_v"$version"_stable_x11.64.zip unzip -n ~/.godot/engine_installers/Godot_v"$version"_stable_x11.64.zip -d ~/.godot/gvfs-trash delete_me.txt##godot mount points, add these to /etc/fstab for mount at startup#/home/mint1/ownCloud-user/godot_files/godot_engine_assets /home/mint1/.godot/engine_assets none bind 0 0#/home/mint1/ownCloud-user/godot_files/godot_engine_installers /home/mint1/.godot/engine_installers none bind 0 0#/home/mint1/ownCloud-user/godot_files/godot_project_exports /home/mint1/.godot/project_exports none bind 0 0#/home/mint1/ownCloud-user/godot_files/godot_project_source /home/mint1/.godot/project_source none bind 0 0#echo -e '\nrun script complete\nPress ENTER to close this window'read -n 1 -s

lmao get good

fugg
how do i make bash script where it layers two lines of "NIGGER" across each other

xinput --set-prop 9 278 -0.8xinput --set-prop 13 348 -0.8clearecho 'APPLIED'
I actually don't know how to script

wtf man

#!/bin/bashecho "NIGGER"echo "NIGGER"

add "#!/bin/bash" to the top of the file by itself

or if your using a faggot version of shell liek zash or if it's in a different directory you may need to change it

Use #!/usr/bin/env bash.

Which systems have bash in another location but do have /usr/bin/env?

Off the top of my head I can think of FreeBSD, probably other BSDs and maybe some Solaris variants, possibly any system using pkg-src too.

From what I've heard, OS X comes with an outdated version of bash, which doesn't understand \e (a reference to octal \033 or hexdecimal \x1b). I guess that's the reason why these faggots switch to zsh. So if you want it portable, don't use \e, if you hate macfags, use \e. I usually go with \033 except a task explicitly needs hexdecimal.

Can confirm. echo can be pretty problematic since echo versions are different from system to system and so are it's flags. Also printf is fucking powerful:

#date
printf '%(%F %T)T\n' -1
#dev to hex
printf '0x%x\n' "65
#echo replacement
printf "%b\n" "$*"
#poor man's ls
printf '%s\n' .[!.]* ..?* *

Just to name a few things.

Feature creep.

POSIX, though.

can you explain why this is preferred?

see for a nice and efficent explanation.

thank you very much user

If it bothers you, you can use this to much of the same effect (it's just longer to type out):
printf %s\\n *ic*
grep is undeniably the wrong solution here, because it assumes that filenames and lines in the output of ls have an exact one-to-one correspondence.

but user, you found a way that works for you.

youtube.com/watch?v=dNw4PwVYzSs

That's mean, user

you're mean

Cry more faggot.

Captcha: bid pig

Have some wallpapers, faggots.
curl -s transparenttextures.com \ | sed -n 's/.*href="\([^"]patterns.*png\).*/http:\/\/www.transparenttextures.com\/\1/p' \ | xargs wget -nv

nudge(){ ping -c 3 "${1:-stallman.org}"}

Here is a pretty handy line of code:
CURRENT_YEAR=$(date +%Y)export CURRENT_YEAR
:^)

If you're using wget anyway, just do this:wget transparenttextures.com/ -r -nd -I '/patterns/' -R '*.html'wget is very powerful.

Something you might like to know about sed is that you don't have to use / as the separator. Anything works. These are equivalent:'s/.*href="\([^"]patterns.*png\).*/http:\/\/www.transparenttextures.com\/\1/p''s|.*href="\([^"]patterns.*png\).*|transparenttextures.com/\1|p'

nanozip.net

...

apt-get updateapt-get upgrade -yapt-get install -y coreutils build-essential gitgit clone github.com/Keith-S-Thompson/random-passwords.git /usr/local/lib/random-passwords/chmod 755 /usr/local/lib/random-passwords/{gen-passphrase,gen-password}ln /usr/local/lib/random-passwords/{gen-passphrase,gen-password} /usr/local/bin/apt-get -y install mariadb-server mariadb-clientapt-get -y install nginxsystemctl start nginx.serviceapt-get -y install php5-fpmapt-get -y install php5-mysqlnd php5-curl php5-gd php5-intl php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-intl php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl

that's some dank autism buddy.

I liked the effect since I first ran a demoscene prod on a computer, this is my first shot at it, but I'm not as masochistic as you so I did it in c.

not nearly as hard as I expected really, I do like your shell version though.

JIM FIX YOUR SHIT BRAH

I wrote this to look at node.js packages and their dependencies. Did I do anything really bad?

#!/usr/bin/env bash#./nom.sh: recursively display node.js modulesnm="node_modules"if [ "$1" = "-h" ]then echo "$0 [dir]: recursively display node.js modules" exit 0fiif [ -z "$1" ]then sdir=./else sdir=$1fiif [ -z "$2" ]then dirl=0else dirl=$2fiif [ -d "$sdir$nm" ]then for ((n=0; n

Hipster has officially lost all meaning. People use zsh because it's the latest and greatest, not because ironic cool.

Not "really bad", but there are mistakes.

Not a mistake, might be a style decision, implies you don't know when to use quotes in bash. The quotes in this statement are redundant.
Two things to address here:
1. echo should never be used with anything except known constant strings which do not begin with a dash. Use printf instead here:
printf '%s [dir]: recursively display node.js modules\n' "$0"
2. The $0 will expand to the full path if the script is invoked on the PATH, so you might want to take the base name:
printf '%s [dir]: recursively display node.js modules\n' "${0##*/}"
3. Square brackets around an argument usually denote that it is optional.
That is a very long-winded way of writing:sdir=${1:-./}dirl=${2:-0}
Missing a slash.if [ -d "$sdir/$nm" ]
Now the user does not need to put a slash at the end of their path (which is not the normal way to refer to the directory). An extra slash in the path (e.g. "/usr///lib") does not cause problems, so it's safer to add it than to just assume it's there.
Several problems:
- Use of echoprintf %s\\n $(basename $sdir)
- Poor quoting (x2)printf %s\\n "$(basename "$sdir")"
- No '--' argument to basename commandprintf %s\\n "$(basename -- "$sdir")"
- Printing a substitution. Just use the command itself. basename -- "$sdir"

Same as with the [ -d ... ] test, this will want a slash between the variables. You can also get rid of the trailing slash in this loop (assuming you do add the slash between sdir and nm everywhere), because you have the check for the node_modules directory later.
An exercise for you, by the way: see if you can prevent your script from getting stuck in symlink loops.
Test it with something like "ln -s . dir", though be aware that this will make your script fork until your process limit is exhausted.
1. You used $0 before, why not again?
2. Ignore the above, why are you re-launching the script at all? You don't need to re-read it, and it's already loaded in memory. Use functions for this.
3. Quoting is wrong

Fixing #1 and #3:"$0" "$d" "$((dirl+1))"

However to fix #2 you'd need to wrap the whole thing in a function. I'll do that, and here's the script after that change and all the above changes:#!/usr/bin/env bash#./nom.sh: recursively display node.js modulesnm=node_modulesif [ "$1" = -h ]then printf '%s DIR: recursively display node.js modules under DIR\n' "${0##*/}" exit 0fiwalk_dir() { local sdir=$1 dirl=$2 d if [ -d "$sdir/$nm" ] then for ((n=0; n

After making a trivial modification to the condition so that it picks up individual packages as well as directories containing lists of packages, it performs more in line with my expectations:
#!/usr/bin/env bash#./nom.sh: recursively display node.js modulesnm=node_modulesif [ "$1" = -h ]then printf '%s DIR: recursively display node.js modules under DIR\n' "${0##*/}" exit 0fiwalk_dir() { local sdir=$1 dirl=$2 d if [ -d "$sdir/$nm" ] || [ -f "$sdir/package.json" ] then for ((n=0; n

Wow! I am enlightened. Thanks.
$ time ./nom.sh[...]real 0m0.322suser 0m0.004ssys 0m0.000s$ time ./nom2.sh[...]real 0m0.021suser 0m0.016ssys 0m0.004s

What do you call what you did with curly braces, for instance
${base##*/} ?

Thank you very much.

I'm im love, please share.

Parameter expansion.

Leaving this here: github.com/koalaman/shellcheck. I'm using it together with syntasic (github.com/scrooloose/syntastic).

You know when people say "it needs some cleanup" and never release? this is one of those times. I feel like putting this magic number ridden spaghetti out there for somebody even less talented than I am to hack on and potentially release is roughly akin to vandalism.

Maybe one day.

What's the best (portable) RANDOM replacement?

POSIX awk has a random number generator.
echo | awk 'BEGIN { srand(); printf("%d\n", rand() * 100); }'
If you run this multiple times per second it'll generate the same number because it uses time in seconds as a seed, so if that's a problem you should call rand() multiple times in a single awk.

get random jewtube link from a channel and play it via mpv
#!/usr/bin/env bashmpv $(youtube-dl --get-url $1 | shuf -n 1)
You'll need youtube-dl and mpv, obviously.
Usage = ./yt-roulette youtube.com/user/DonaldTrumpVEVO

well it hangs until it lists all videos so use at your own risk. Add --playlist-end 50 to reduce it to 50 videos.

...

You should quote your variables. "$1" instead of $1, or spaces and other special characters will mess it up.

And this is better:mpv --shuffle "$1"mpv has a youtube-dl hook, so you don't need to call youtube-dl explicitly.

This has nothing to do with shell scripting. Did you post in the wrong thread?

He wanted to show off his scary maze ripoff

It that an rare apng? How to create these?

apngasm

Also ffmpeg can create them, but you don't get nearly as much control.

Spoonfeed me, mighty wizards.

I'm trying to convert our imageboard's epoch format into human-readable date.

date makes it easy for default timestamps:
date -d @1464445567
But it fails for timestamps with miliseconds.

My current solution:
date -d @$((1464445567907 / 1000))
... but it just doesn't please me. How to do it right?

That seems like the right way to do it. Why doesn't it please you?

If it's too complex to type, just put it in a shell function:
ib2date () { date -d @$(($1 / 1000))}

Formatting reasons, precision.

date -d @1464444193 "+%F %H:%M:%S" works, but what I'm really looking for is:
date -d @1464444193727 "+%F %H:%M:%S.%3N"

Which formatting and precision problems does it have?

Oh, I missed the .%3N. There are no precision problems, because it rounds downwards. Try this:
ib2date () { echo "$(date -d @$(($1 / 1000)) "+%F %H:%M:%S").$(($1 % 1000))"}

That's pleasing! Shame I didn't think of that myself... Anyway, thank you for the heads up.

pls no bully ty

Why the echo?

zsh and fish users: Don't be shy. OP is always a faggot, you know? :^)

I expected it to wait for input if you didn't give it like that, but apparently it doesn't if it already knows it won't process further input. I didn't know that when I posted that.

I tested with gawk, mawk and busybox awk, and all of them didn't need the echo, but it looks like POSIX doesn't require that behavior.

This snippet will convert stuff like
*color7: #dddddd from ~/.Xresources into console escapes codes.
When you hit CTRL+ALT+F1, your tty will look like your xterm/urxvt/etc.

.bashrc:

if [[ -z "${DISPLAY}" ]]; then sed -n 's/.*\*color\([0-9]\{1,\}\).*#\([0-9a-fA-F]\{6\}\).*/\1 \2/p' \ "${HOME}/.Xresources" | awk '$1 < 16 {printf "\033]P%X%s\007", $1, $2}'fi

Nice. [[ has the same result as [ here, so use [ instead, so it's compatible with more shells.

What's wrong with zsh? Serious question.

I'm presenting you this amazing small, but feature-rich client for mpd. Run it without arguments to see a list of supported commands.

# Netcat Mpd Clientnmc() { # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see gnu.org/licenses/>. printf '%s\n' "${@:-commands}" | nc localhost 6600}

Basically one doesn't even need nc. Found this somewhere on the web (is cat even needed?):

tmc () { exec 3 /dev/tcp/localhost/6600 printf '%s\nclose\n' "$@" 1>&3 cat 0

/dev/tcp doesn't really exist, though. It's a bash feature. Won't work in other shells.

This works as a replacement for cat without arguments:
cat () { while IFS= read -r line; do printf "%s\n" "$line" done}

Technically nothing. zsh on it's own, without any frameworks, _can_ be an improvment, but most new users install it for idiotic reasons like, having a colored PS1 and stuff like that.

Fish on the other hand (afaik) isn't POSIX complete.

Also see:

Oh, didn't know it's bash only. Then nc is maybe the lesser evil.

fish isn't POSIX at all, but it doesn't try or want to be.

It stands for "friendly interactive shell", and that's what it is. Friendly for interactive use, but bad for scripts. It doesn't have a lot of advanced control features. It uses more pleasant syntax than bourne, without "then" and "do", and with "end" instead of "esac", "fi" and "done".

It has very nice predictive autocompletion and some other tricks like syntax highlighting and man page parsing. I used it for a while but I kept launching other shells for advanced use.

what the fuck

can't you do that with bash?

I mean I do it with mint and I have done it with CentOS7 and I think that was Bash

Any shell with a PS1 supports that, because you can just directly put escape codes in it, but zsh has more sophisticated theming stuff.

oh ok, that is a stupid reason then

You just made me giving fish another try.

Sort of related:

I was thinking about writing a small sed script for syntax highlighting input or output when using bash. Is there a way to set up a shell trap or something that allows me to manipulate text before bash is printing it?

bretty good, saved into my cripple collection:
ls() { printf '%s\n' .[!.]* ..?* *}echo() { printf '%b\n' "$*"}
/r/ing more

Forgot date.

date() { printf '%(%F %T)T\n' -1}

I tried implementing basic Unix utilities in POSIX sh once, and I got as far as this:
plain_pipe () { while IFS= read -r line; do printf "%s\n" "$line" done}cat () { if [ "$#" = 0 ]; then plain_pipe fi for arg in "$@"; do if [ "$arg" = "-" ]; then plain_pipe else plain_pipe < "$arg" fi done}ls_dir () { old_pwd="$PWD" cd "$1" && for file in *; do printf "%s\n" "$file" done cd "$old_pwd"}ls () { if [ "$#" = 0 ]; then ls_dir . elif [ "$#" = 1 ]; then ls_dir "$1" else for arg in "$@"; do printf "%s\n" "$arg:" ls_dir "$arg" done fi}touch () { for arg in "$@"; do : >> "$arg" done}false () { return 1}true () { return 0}yes () { while true; do printf "%s\n" "${1:-y}" done}pwd () { printf "%s\n" "$PWD"}tee () { while IFS= read -r line; do printf "%s\n" "$line" >> $1 printf "%s\n" "$line" done}
As long as printf and [ are built-ins it's pure POSIX sh.

You could paste this into the shell of a system without even busybox (on old Android versions for example).

You have some prominent bugs in the tee function:
- you must quote the $1
- you're reopening the file every time
- it's behaving like "tee -a"

Attempted fix:tee() { if [ "$1" = -a ]; then shift append=true else append=false fi [ "$1" = -- ] && shift if $append; then exec 3>>"$1" else exec 3>"$1" fi while IFS= read -r line; do printf %s\\n "$line" >&3 printf %s\\n "$line" done}
There are of course far more bugs lurking here (mandatory line buffering; deadlock potential; discarding data past the final newline; NULL-unsafe strings), but that's a start on a couple.

Oh yeah, read this. Specifically "Command Search and Execution". It guarantees that "true", "false" and "pwd" are builtins, among others.
pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html

I guess I should also have put tee in a subshell up there. FD 3 may be in use, and it also needs to be closed when tee dies.

finally got around to updating this thing

#!/usr/bin/env bash#made for linux mint 17.2[ $# = 0 ] && exec gnome-terminal -e "bash -- '${0//\'/\'\\\\\'\'}' --no-term"mkdir ~/.godotcd ~/.godot || exitpwdls -lsudo -vwget -O delete_me.txt downloads.tuxfamily.org/godotengine/ && cat delete_me.txt | grep 'href="2'echo -e '\nAbove is a directory list of the curent versions of the godot engine'echo 'Please enter the version number you would like to download,'echo -n 'then press [ENTER](ex. "2.0.3"): '; read version; echo $versionmkdir ~/.godot/engine_assetsmkdir ~/.godot/engine_installersmkdir ~/.godot/project_exportsmkdir ~/.godot/project_sourcesudo umount ~/.godot/engine_assetssudo umount ~/.godot/engine_installerssudo umount ~/.godot/project_exportssudo umount ~/.godot/project_sourcesudo mount --bind ~/ownCloud-user/godot_files/godot_engine_assets ~/.godot/engine_assetssudo mount --bind ~/ownCloud-user/godot_files/godot_engine_installers ~/.godot/engine_installerssudo mount --bind ~/ownCloud-user/godot_files/godot_project_exports ~/.godot/project_exportssudo mount --bind ~/ownCloud-user/godot_files/godot_project_source ~/.godot/project_sourcecp -n ~/ownCloud-user/godot_files/godoticon.png ~/.godotpwdls -lwget -nc -O ~/.godot/engine_installers/Godot_v"$version"_stable_x11.64.zip downloads.tuxfamily.org/godotengine/$version/Godot_v"$version"_stable_x11.64.zipwget -nc -O ~/.godot/engine_assets/Godot_v"$version"_stable_export_templates.tpz downloads.tuxfamily.org/godotengine/$version/Godot_v"$version"_stable_export_templates.tpzunzip -n ~/.godot/engine_installers/Godot_v"$version"_stable_x11.64.zip -d ~/.godot/unzip -o ~/.godot/engine_assets/Godot_v"$version"_stable_export_templates.tpz -d ~/.godot/grep "#godot mount points" -q /etc/fstab && echo "comment exists" || sudo sed -i "$ a #godot mount points" /etc/fstabgrep "/home/mint1/ownCloud-user/godot_files/godot_engine_assets /home/mint1/.godot/engine_assets none bind 0 0" -q /etc/fstab && echo "mount point exists" || sudo sed -i "$ a /home/mint1/ownCloud-user/godot_files/godot_engine_assets /home/mint1/.godot/engine_assets none bind 0 0" /etc/fstabgrep "/home/mint1/ownCloud-user/godot_files/godot_engine_installers /home/mint1/.godot/engine_installers none bind 0 0" -q /etc/fstab && echo "mount point exists" || sudo sed -i "$ a /home/mint1/ownCloud-user/godot_files/godot_engine_installers /home/mint1/.godot/engine_installers none bind 0 0" /etc/fstabgrep "/home/mint1/ownCloud-user/godot_files/godot_project_exports /home/mint1/.godot/project_exports none bind 0 0" -q /etc/fstab && echo "mount point exists" || sudo sed -i "$ a /home/mint1/ownCloud-user/godot_files/godot_project_exports /home/mint1/.godot/project_exports none bind 0 0" /etc/fstabgrep "/home/mint1/ownCloud-user/godot_files/godot_project_source /home/mint1/.godot/project_source none bind 0 0" -q /etc/fstab && echo "mount point exists" || sudo sed -i "$ a /home/mint1/ownCloud-user/godot_files/godot_project_source /home/mint1/.godot/project_source none bind 0 0" /etc/fstabgvfs-trash delete_me.txtecho -e '\nrun script complete\nPress ENTER to close this window'read -n 1 -s

I'll probably add variables later for the mounting directories to shorten the whole thing

That's better, thank you. I should get more used to advanced file descriptor usage.

You forgot to close the file, so I did that, and I also stopped it from depending on true and false:tee() { if [ "$1" = -a ]; then shift append=true else append=false fi [ "$1" = -- ] && shift if [ "$append" = true ]; then exec 3>>"$1" else exec 3>"$1" fi while IFS= read -r line; do printf "%s\n" "$line" >&3 printf "%s\n" "$line" done exec 3>&-}

I replied a little later after realizing that - I think it should go in a subshell, so that it doesn't close FD 3 for the rest of the script if it's already in use.

That said it will probably be piped anyway, which usually puts it in a subshell, but that can't be relied on.

As for relying on true/false, I don't think that's a bad thing. They're always going to be builtins on a POSIX shell, and you've already redefined them anyway.

meh, nothing special here. just use this for the output on my i3bar.

while true; doecho `mpc | sed -n 1p` " " `mpc | sed -n 2p` " " `mpc | sed -n 3p` "| Dropbox: " `dropbox status` " | " `date`sleep 1done

I think this works, and is a lot more efficient because it doesn't call mpc as much:
while true; dompc | head -n 3 | tr '\n' ' 'echo "| Dropbox: " `dropbox status` " | " `date`sleep 1done

thanks. completely forgot about tr and getting them all on the same line was the whole reason I strung them together that way.

You can get rid of the "head" if mpc only has three lines of output, of course.

which it does.

echo `mpc | tr '\n' ' '` "| Dropbox: " `dropbox status` " | " `date`

Use $(...). The backtick syntax has been considered deprecated forever due to poor interaction with quoting, difficulty nesting, and visual ambiguity.

Also,while true; do printf '%s | Dropbox: %s | %(%F %T)T\n' "$(mpc | paste -s -d ' ')" "$(dropbox status)" -1 sleep 1done
Using the bash-specific %(...)T format. You might want to use %s and substitute the date command in if you're in posix sh.

Another way to go about it:
join() { # >why not just use paste # because it doesn't support multi-char delims delim=$1 output= IFS= read -r output while IFS= read -r line; do output=$output$delim$line done [ -n "$line" ] && output=$output$delim$line printf %s\\n "$output"}while true; do { mpc | join ' ' printf 'Dropbox: %s\n' "$(dropbox status)" date } | join ' | ' sleep 1done
That's POSIX sh compatible, and I feel like the loop is a bit easier to read (though the join function is a bit of a mouthful).

There is literally nothing that bash does better than zsh, fucking retard.

hue hue hue

dohoho

seems overly complex for just a quick i3 bar output.

meant for

I'm aware the "join" looks a little complex, but I think it simplifies the actual usage of the code (inside the loop).

Though, that's why I wrote the first script. Keeping it relatively simple while still keeping it correct.

#!/usr/bin/env shfor i in $(seq 1 100); do if [ $((i % 15)) -eq 0 ]; then printf 'FizzBuzz ' elif [ $((i % 3)) -eq 0 ]; then printf 'Fizz ' elif [ $((i % 5)) -eq 0 ]; then printf 'Buzz ' else printf '%s ' "$i" fidone
Pls no bully.

wake me up

I think it needs more newlines

imagefap-dl

#!/usr/bin/env bash[ -z "$1" ] && { printf 'Usage: imagefap-dl [url]\n' >&2 exit 0}id=$(printf "$1" | sed 's/.*pictures\///; s/\/.*//');list=$(wget -qO- "imagefap.com/pictures/$id/?view=2" \ | grep -o 'fap.to/images/thumb/[^"]*' \ | sed 's/thumb/full/')wget -nv -nc $list -P $id
Improvements welcome.

Not mine, just for reference:
seq 1 100 | while read L; do F=$(($L % 3)) B=$(($L % 5)) [ $F -eq 0 ] && echo -n Fizz [ $B -eq 0 ] && echo -n Buzz [ $F -ne 0 ] && [ $B -ne 0 ] && echo -n $L echodone
btw, is seq POSIX?

seq is not POSIX. You can do this:i=1while [ i != 100 ]; do echo $i i=$((i + 1))done | while read L; do...

Or don't use pipes in the first place.

Speaking of pipes, here's how a real man does pipes
l(){ while :;do printf $@;done;};e(){ exec 3

...

Yeah, it's obviously better to do it without piping. This was the quickest way to replace seq.

I whipped this up for a simple netstat solution in conky. Any suggestions for improvements?

#!/bin/bash# number of lines to start concatenationmaxlen="14"output="$(netstat -ap | grep 'ESTABLISHED' | grep -v -e ntp | awk '{ printf("%-26s %-23s %-23s %s\n",$7" ("$1")",$4,$5,"") }' | funiq -ci -d 15 )"l=$(echo "$output" | wc -l)#echo "$l `expr $l - $(echo "$output" | grep -c -e localhost)` $maxlen"if [[ "$l" -ge "$maxlen" ]]; then if [[ "`expr $l - $(echo "$output" | grep -c -e localhost)`" -ge "$maxlen" ]]; then echo "$output" | grep -c -e localhost | awk '{ printf("%-26s %-23s %-23s %s\n","*/* ["$1"]","localhost:*","localhost:*","") }'; echo "$output" | grep -c -e $(ps ax | grep ppapi-flash-path | grep -v grep | head -1 | awk '{print $1}') | awk '{ printf("%-26s %-23s %-23s %s\n","*/inox ["$1"]","*:*","*:*","") }'; echo "$output" | grep -v -e localhost -e libpepflash else echo "$output" | grep -c -e localhost | awk '{ printf("%-26s %-23s %-23s %s\n","*/* ["$1"]","localhost:*","localhost:*","") }' echo "$output" | grep -v -e localhost fi else echo "$output"fi

e:

e() { echo -e "\e#8"}

Does what it says on the tin.

#!/usr/bin/env bashset -euo pipefailhostname=${1:-}# Prints the specified message to standard error and exits with abnormal# status.abort() { echo -e "${1}" 1>&2 exit 1}# Prints the usage for this script.print_usage() { abort "Usage: knock-mosh \n"` `"\n"` `"Positional arguments:\n"` `" hostname - The host to connect to."}# Knocks on the predefined ports then connects to the host via mosh.activate_it() { PORTS=(13 420 42013) echo -n "Knocking on port " for ((i=0; i < ${#PORTS[@]}; i++)); do if [[ ${i} != 0 ]]; then for ((j=0; j < ${#i}; j++)); do echo -ne "\b" done fi echo -n "$((${i} + 1))" knock ${hostname} ${PORTS[$i]} done echo "... done!" echo "Connecting via mosh..." mosh ${hostname}}main() { if [[ -z ${hostname} ]]; then print_usage fi activate_it}main

What's the intended use of that escape? Is it meant for use with the sequences which change your codepage?


You use pipefail exactly 0 times.
The "set -euo pipefail" maymay needs to die already. Pipefail is a needless bashism which prevents you from switching to better shells like dash, "set -u" is for people who've never heard of the "?" parameter expansion, and "set -e" is a poorly conceived hack, which I don't think is ever suitable as a default.

"set -e" fetishism is, in my opinion, newbie programmers lamenting "wow bash sure is hard, I wish everything threw exceptions".

No.
This is cancer. Use printf, which is more standardized and predictable.

Why braces? Since they do nothing at all in the contexts where you've used them, they scream "inexperienced" to me. Is there a reason for them?

Not an environment variable. Do not capitalize.

Just use $* in abort already, or rework it a little and use a heredoc.

Please quote correctly.

On another note, regarding this: echo -n "Knocking on port " for ((i=0; i < ${#PORTS[@]}; i++)); do if [[ ${i} != 0 ]]; then for ((j=0; j < ${#i}; j++)); do echo -ne "\b" done fi echo -n "$((${i} + 1))" knock ${hostname} ${PORTS[$i]} done
Why not restructure it like this? i=0 for port in "${PORTS[@]}"; do printf '\r%s' "Knocking on port $((++i))" knock "$hostname" "$port" done

I don't have the most experience writing bash scripts but I don't consider myself a mouth breather.

Set those flags on every shell script that I write so they behave sensibly.

I understand you're trying to be helpful but you reek of a superiority complex. Things behaving sensibly is not a Bad Thing™. Uninitialised variables being replaced by empty strings is a war crime.

Fair enough.

Using braces is safer. And if I'm going to use braces, I'll use them consistently.

It's a constant, so I would assume you would capitalise it, but alright.

I'm going to need an example here.

That's pretty dope, definitely more concise.

Jesus Christ, everything is so ugly except C

Bash looks like shit

It is, but it's the best tool we have.

Environment variables are capitalised, so it's better to never capitalise shell variables so you don't accidentally override them.

If you use $* instead of $1 it inserts all arguments in the string, not just the first one. That way you could get rid of the interesting abuse of backticks (I've never seen them used that way before) and use backslashes instead.

I see, thanks for the tip.

That I may have to admit to, at least in the domain of shell scripting. Sorry about that.

I don't consider it sensible behaviour. I consider it a different and out-of-place culture, as if Americans suddenly came to China and brought knives and forks with them to restaurants because they're the "one true way" to eat.

In what sense?

I'll explain a little why I was wary of that. Usually the reason ${var} triggers a red flag for me is because bash newbies often think it's a replacement for variable quoting (which you probably know, it's not).

I was hoping to eke out an explanation as to what you thought it changed when contrasted with $var, but I think I only got halfway there.

Shell convention is to use capitals for things which are in the environment, since the shell (regrettably) shares a namespace for environment and shell variables. Capitalisation just happens to be how people have chosen to make the distinction, as a kind of pseudo-namespace chosen by character set. The only common exception to this rule is the environment variable "http_proxy".

Using $*:abort() { IFS= printf %b\\n "$*" >&2 exit 1}print_usage() { abort "Usage: knock-mosh \n" \ "\n" \ "Positional arguments:\n" \ " hostname - The host to connect to."}
Using heredocs (warning in advance, the "-" in a heredoc is a tab-stripping operator, which does not work on spaces):abort() { cat >&2 exit 1}print_usage() { abort

do not use != "", use -n

head -num is deprecated use head -n num

no need for quotes in simple assignments like file_in="$1"
since your using bash you should use ${sar/:/\/} instead of sar=`tr ':' '/'

pick up on the ls | grep cancer too
It's using ; as the delimiter for the 's' command, not as a command separator
perl is more likely to be installed, especially on Arch Linux
It's also awkward (a reimplementation of something like nohup?) and I'm surprised given your opinions towards other things that you don't consider it bloat.
Is there a reason? It comes with all linuxes and BSDs I've ever seen, and the alternative is making it from scratch.

seq is not POSIX, so there probably are systems out there without it.

A simple, one-line binary clock. Makes checking the time less boring.

_get_binary_time() { for i in $(date +"%H%M" | sed 's/\(.\)/\1 /g'); do case "$i" in 0) printf '0000 ';; 1) printf '0001 ';; 2) printf '0010 ';; 3) printf '0011 ';; 4) printf '0100 ';; 5) printf '0101 ';; 6) printf '0110 ';; 7) printf '0111 ';; 8) printf '1000 ';; 9) printf '1001 ';; esac done | sed 's/ / /g; s/ $//' }

I guess it could be shorter, but well.

Whats the best way to print a huge block of text without the pain of escaping everything?

text='need to escape: ' '
text="need to escape: " "
cat

Why are you converting individual digits instead of numbers?
{ printf "obase=2; print "; date +'%H," ",%M,"\n"'; } | bc

Once for all:
When to use env and when not?

Your way is indeed much nicer. Thanks.
Fixed!

You use env when the binary could be in a lot of different places in the filesystem.

Python varies from distro to distro. Bash is usually in /bin, but a lot of systems that don't ship with it put it somewhere else. But any system that has /usr/bin/env will also have sh in /bin, and some systems with sh in /bin don't have /usr/bin/env.

Nice solution. I really should read myself into bc.

I see, so there's no standard solution; one must use env individually when it makes sense, right?

Yet another mandelbrot. Saved this from some code golf thread somewhere.
#!/bin/bashfor h in {-4096..4096..200}; do for g in {-8192..4096..115}; do x=0 y=0 for((i=0;i11)+h)) x=$v done printf '%s' "$((i%10))" done printf '\n'done

What's wrong with cat

It breaks when the text contains a '

Whoah, it actually doesn't.

Mea culpa.

But I want my clock in HEX. What do?

replace 2 with 16

Hex can be done without bc too, since printf supports hex:
date +'%H %M' | { read hour minute printf '%02X:%02X\n' "$hour" "$minute"}

Or just with printf.
printf '%02X:%02X\n' \ "$(printf '%(%H)T' -1)" \ "$(printf '%(%M)T' -1)"

True, but that's twice the forking and not POSIX.

Actually there's another problem too. You're getting 2 different dates. That means it could show "0B:00" at midday if the hour ticks over while it's checking the minute.

Damn. Thnx for the heads up.

I wrote this awk function way back when to shift subtitle timings, and therefore burn subtitles into a video faster, for a front-end script to ffmpeg:
shiftSubtitleTimings(){ awk -v "offset=$STS" ' function stamp2sec(timestamp) { split(timestamp,tfields,":") ret=0 if (tfields[3]) { ret = tfields[1]*60*60 + tfields[2]*60 + tfields[3] } else if (tfields[2]) { ret = tfields[1]*60 + tfields[2] } else { ret = tfields[1] } return ret } function sec2stamp(time) { hour = sprintf("%d",time/(60*60)) minute = sprintf("%d",time/60) sec = sprintf("%d",time) dec = sprintf("%d",time*100)%100 return hour":"minute":"sec"."dec } BEGIN {FS=",";off=offset} {doprint=1} /\[Events\]/ { events=1 } events && /^Dialogue/ { doprint=1 time=stamp2sec($2) if (time-off >= 0) { sub($2,sec2stamp(time-off)) time=stamp2sec($3) sub($3,sec2stamp(time-off)) } else { doprint=0 } } doprint {print}'}

Called with
ShiftSubtitleTimings < subs-nonseeked.srt > subs.srt

Which reminds me, I need to integrate this fastseeking into github.com/Kagami/webm.py

This user took my script and made it much better, aside from that little implementation detail.
Most of it was garbage, being something I shit out with really no regard in a day or so in the timespan of a few months so that I didn't have to keep fucking around with the same options I had already set.
And make the tedious task of cutting/cropping videos easy, with the mplayer and the rectangle filter.

Does arch linux not come with bc? but comes with perl? bc is defined in posix.

i=0; while [ $((i+=1)) -le 100 ]; do ...
$ command -V seq
seq not found


There is a standard solution, do not use a shebang for sh. From posix: "If the first line of a file of shell commands starts with the characters "#!", the results are unspecified." but it is specified that "shall execute a command interpreter and the environment of the executed command shall be as if the process invoked the sh utility using execl() as follows:

execl(, arg0, file, arg1, ..., (char *)0);

where is an unspecified pathname for the sh utility, file is the process image file, and for execvp(), where arg0, arg1, and so on correspond to the values passed to execvp() in argv[0], argv[1], and so on."


while, if, etc take compound lists, it allows for things like: if (true) then (echo hello, world) fi
do while loops can be done like: while body; condition; do :; done

function mpc-add-random-album(){ 1=${1:-1} mpc list album | shuf | head -n $1 | tee >(while read -r i; do echo Album \""$i"\" added to playlist.; done) | sed "s/'/\\\'/g" | xargs -I{} mpc findadd album '{}'}function mpc-del-album(){ if [ $# != 1 ] then ALBUM="$(mpc -f "%album%" playlist | uniq | tail -n 1)" else ALBUM="$(mpc -f "%album%" playlist | grep -i ".*$1.*" | uniq | tail -n 1)" fi mpc -f "%position% %album%" playlist | grep -F "$ALBUM" | cut -d ' ' -f1 | mpc del echo Album \""$ALBUM"\" removed from playlist.}function mpc-watch(){ watch -n1 -t "mpc status; echo; mpc -f '%artist% #|[ (%date%)] %album% #| %title%' playlist"}
Anything to improve?

I use ROX file manager, and I wanted a simple way to change the wallpaper.
pwallpaper only searched for images in a certain folder, but I wanted to have a dedicated folder in my files folder, so it didn't waste space in the sfs. So I made this script.

It's all hardcoded and ugly, I never intended to share it, but you can have it if you want. I'm a newcomer.

[code=bash]#!/bin/bash
#change-wall.sh script for changing wallpaper on ROX pinboard
#licensed under public domain
PARAM=$1
FILE=$2
if [ ${PARAM} == "s" ];
then
sed -i "3s|.*| $FILE|" "$HOME"/Choices/ROX-Filer/PuppyPin
elif [ ${PARAM} == "c"];
then
sed -i "3s|.*| $FILE|" "$HOME"/Choices/ROX-Filer/PuppyPin
elif [ ${PARAM} == "t"];
then
sed -i "3s|.*| $FILE/" "$HOME"/Choices/ROX-Filer/PuppyPin
fi
rox -p "$HOME"/Choices/ROX-Filer/PuppyPin
#exit 0[/code]

#!/bin/bash#change-wall.sh script for changing wallpaper on ROX pinboard#licensed under public domainPARAM=$1FILE=$2if [ ${PARAM} == "s" ]; then sed -i "3s|.*| $FILE|" "$HOME"/Choices/ROX-Filer/PuppyPinelif [ ${PARAM} == "c"]; then sed -i "3s|.*| $FILE|" "$HOME"/Choices/ROX-Filer/PuppyPinelif [ ${PARAM} == "t"]; then sed -i "3s|.*| $FILE/" "$HOME"/Choices/ROX-Filer/PuppyPinfirox -p "$HOME"/Choices/ROX-Filer/PuppyPin#exit 0

This is the definition of bloated retardation.

Remove the 'function' in your function definitions

Parameters can not be directly assigned to like that. replace 1=${1:-1} with something like: n=${1:-1}
No idea what shuf is, or how mpc works but i would remove the head | tee >(while...) | sed | xargs and use something like:
mpc list album | shuf | while [ $((n-=1)) -ge 0 ] && IFS= read -r album; do mpc findadd album "$album" && printf 'Album "%s" added to playlist.\n' "$album"done

Do not use UPPERCASE for non environmental variables.
I would replace the if else with a case, but just personal preference.
No need to quote in simple variable assignments like that, but does not make a difference.
No reason to use .*re.* for searches, just re will work.
No reason to use uniq if you just want the last line.
case $# in 1) album=$(mpc -f '%album%' playlist | grep -- "$1" | tail -n 1) ;; *) album=$(mpc -f '%album%' playlist | tail -n 1) ;;esac
In this case there is no need to care about the amount of parameters at all, grep -- "" will match everything so you can just use:
album=$(mpc -f '%album%' playlist | grep -- "$1" | tail -n 1)
I would use printf instead of echo
printf 'Album "%s" removed from playlist.\n' "$album"

oops, i did not intend to indent those cases, just style though

You need to quote your variables
In test/[] use = not == to test for equality
But a big elif chan to test against constants is ugly, use case
Do not use sed -i, use ed, or if you must use sed use a temp file

possibly something like
file=${2:?please specify a file}case $1 ins) type=Streched ;;c) type=Centered ;;t) type=Tiled ;;*) exit 1esaced -s "$HOME"/Choices/ROX-Filer/PuppyPin $file.w!rox -p "$HOME"/Choices/ROX-Filer/PuppyPin

Heh, why? zsh.sourceforge.net/Doc/Release/Functions.html there doesn't seem to be any problem.
It better in some places but worse in others. Thanks for the tip anyway.
I-it was late when I made it.
Nice, forgot about it.

Forgot what's the difference. Printf is POSIX?

Anyway, thanks for the advice.

Also
Werks for me (tm)

It breaks compatibility with other shells without providing any extra functionality.

I guess you're right. I usually keep my scripts sh compatible, but I haven't used anything else than zsh for interactive use for a long time now

Did not know it was zsh, never used it, my reply was posix sh.

printf is posix. echo is horribly different between versions, some take options, some do not and posix says it can not take -- as end of options, but allows it to take options.
For example if v=-neEEEEEEEEEEEEEEE
on some versions of echo, including bash(depending on compile time options) and gnu
echo "$v"
will print nothing at all, but with others it will print the contents of $v followed by a newline. with gnu echo if $v is --help or --version it would have printed some big banner instead of the literal string.
printf takes a format string and allows for advanced text formatting options and consistent behavior

So now, I have the much more cleaner
mpc-add-random-album(){ mpc list album | shuf | head -n ${1:-1} | while read -r album do mpc findadd album "$album" && printf 'Album "%s" added to playlist.\n' "$album" done}mpc-del-album(){ album=$(mpc -f "%album%" playlist | grep -i -- "$1" | tail -n 1) mpc -f "%position% %album%" playlist | grep -F -- "$album" | cut -d ' ' -f1 | mpc del printf 'Album "%s" removed from playlist.\n' "$album"}

I forgot to mention that you can't have - in your function names if you want it to be posix. I would quote the ${1:-1}. Your read will strip whitespace.

I should mention that this does allow for code execution, for example something like:
commandname s '
.
!rm -rf $HOME
'

if you care and have mktemp you could do something like
tmp=$(mktemp) || exittrap 'rm -f -- "$tmp"' EXIT{ sed 2q "$HOME"/Choices/ROX-Filer/PuppyPin printf ' %s\n' "$type" "$file" sed 1,3d "$HOME"/Choices/ROX-Filer/PuppyPin} >"$tmp"mv -- "$tmp" "$HOME"/Choices/ROX-Filer/PuppyPin

and...without using sed the block could be
( IFS= read -r line; printf '%s\n' "$line" read -r line; printf '%s\n' "$line" read -r line; printf ' %s\n' "$type" "$file" cat # or while read -r line; do printf '%s\n' "$line"; done; printf %s "$line") "$tmp"

Thanks, this is much cleaner, or as clean as bash can get.
I was an afternoon with no internet trying to get it working and it never ocurred to me that bash would have cases.
Also, in the *) option I suppose is if no previous case conforms, is that correct?

Yes.

Also I'd recommend 2 more changes over that user's script:

1. Show an error if you fall into the * case (e.g. printf 'Mode must be s, c, or t\n' >&2)
2. Use /

Learned something new. Thanks.

C U C K
U
C
K

what a great contribution to the thread.
you should probably kill yourself asap.

Shell guy, is using shellcheck and 'fixing' all the items it lists good practice?

Use it as a guide to point out things you missed. If you don't completely understand something it tells you learn about it and experiment with it first, and then decide whether to follow it or not.

One thing in particular you can ignore is its suggestion to quote variables in output redirection files. There's no difference between these:command > $fcommand > "$f"
But it tells you the first one is wrong anyway.

[CODE]echo test > foo bar && cat foo[/CODE]

Sure, but it works differently with variables.
$ f='foo bar'$ echo test >> $f$ cat 'foo bar'test

So I wanted to alternate wallpapers each reboot (basically each time .xprofile is read) and this provided me with a nice challenge. Cast your eyes on this shitty hack:
#!/bin/shif [ "$(tail -n -1 "$0" | grep -F 'rachnera')" ]then sed -i '$s#.*#hsetroot -full ~/wp_miia.png#' "$0"else sed -i '$s#.*#hsetroot -full ~/wp_rachnera.png#' "$0"fihsetroot -full ~/wp_rachnera.png
Anyone has a cleaner/cleaverer implementation, or an idea for cycling through n wallpapers?

Do this instead:if tail -n -1 "$0" | grep -Fq 'rachnera'Does it have to cycle, or would picking a random wallpaper be okay?

If taking a random wallpaper is alright I'd do this:hsetroot -full "$(shuf -e -n 1 ~/wp_*)"

Of course random would be easy. But cycling sure is painful (especially when reaching the end).

#!/bin/bashimages=(~/wp_*.png)imgnum=7imgnum=$(( ($imgnum + 1) % ${#images[*]} ))sed -i "s/^imgnum=[0-9]\+$/imgnum=$imgnum/" "$0"hsetroot -full ${images[$imgnum]}

I figured something out. It uses a text file with a list of filenames of wallpapers at ~/wallpapers. I suck at awk so it probably breaks if there's whitespace in the filenames.
hsetroot -full "$(head -n 1 ~/wallpapers)"awk -i inplace 'NR == 1 { f=$1 }NR > 1 { print $1 }ENDFILE { print f }' ~/wallpapers

m8, the whole game is to have a self contained script; it would be pretty easy with symlinks, otherwise.

The only way to do that is with a self-editing shell script and that's something you really shouldn't have, especially because shells don't read the whole file before they start executing.

#!/bin/shwp="$(ls -1 ~/wp_*.png)"n=1n=$(( (n + 1) % $(echo "$wp" | wc -l) ))sed -i "s#n=[0-9]\+#n=$n#" "$0"echo "$(echo "$wp" | sed -n "$((n + 1))p")"
posix sh compatible (thus no arrays)

You're right, but every shell will probably read such a tiny script in one time. Still a hack, but a cool hack.

So, to a scrub and can't program, what's the difference between Sh and Bash and what makes it matter?

Bash is a clone of sh with extra features. All sh code will work in bash, but not all bash code will work in all versions of sh because it might use special features bash has that are not in the standard.

A lot of operating systems come with a version of sh, but not bash, and some operating systems that do come with bash also come with a version of sh that's much faster than bash.

It's good practice to not use any bash features you don't need.

why

When you l but k.

k() { array=(" " ░ ▒ ▓ █) while :; do printf '\033[%s;%sf%s' \ "$((RANDOM%LINES+1))" \ "$((RANDOM%COLUMNS+1))" \ "${array[RANDOM%5]}" done}

Now that's cool.

You have better? Globs don't have proper delimiters and this use of echo is safe (no options). Sure, printf blabla but this isn't really important. Actually, sed can be replaced by cut -d$'\n' -f

[dwarf fortress miasma PTSD intensifies]

A slightly more correct way to get the number of files is this:
argcount () { echo "$#"}argcount ~/wp_*.png
It doesn't fuck up when there's a directory matching ~/wp_*.png or a file with a newline in it.

And to get the nth file:
ntharg () { n=$1 shift eval "printf '%s\\n' \"\$$n\""}ntharg "$n" ~/wp_*.png

find -maxdepth 1 -type f -iname "wp_*.png"cut -d $'\0' -f
is better in fine. Handles newlines and no shell fuckery.

Shit, forgot that only zsh has NULL byte in strings. Solved it with a function.
#!/bin/shwp(){ find "$HOME" -maxdepth 1 -type f -iname "wp_*.png" -print0}n=0n=$(( (n + 1) % $(wp | xargs -0n1 echo | wc -l) ))sed -i "s#n=[0-9]\+#n=$n#" "$0"hsetroot -full "$(wp | cut -d $'\0' -f $((n + 1)))"

Learned that c style bytes isn't POSIX. The fucking fix is horrible:
bash, ksh:a=$' \t\n'POSIX:a="$(printf '%b_' ' \t\n')"; a="${a%_}" # protect trailing \n
So I just use sed -z -n like the good GNUgoy I am.

Actually echo $'\t'abcd does what I expect it to do in sh. Any idea why?

Which sh is it?

Its bash. Probably turns into --posix mode when argv[0] is /bin/sh

I heard bash POSIX mode still has a lot of extensions.

Try busybox sh if you have it installed. Otherwise maybe dash or ash. Those are ash, which has a few extensions, but not a lot of them.

Works in busybox sh too. What about posh? Why does Debian have two shells that are sypposedly POSIX?

It doesn't work in dash.

Basically, I'm crushing my nuts for nothing since none of those -print0 -0 or -z are in POSIX. So now, the real question is:
Do I use nonstandard options because POSIX says that the only forbidden chars in filenames are / and \0 or do I become vulnerable to shitty files?

I suggest everyone puts pubs.opengroup.org/onlinepubs/9699919799/ in their bookmarks.

Currently I'm using this function to restart a process:

restar () { ( sh -c "pkill $1; sleep 1; $1" & )}
Wondering if there's a better way?

I've no idea what I'm doing.

dash is significantly faster and more efficient than bash, and it helps filter out shell scripts that claim to be sh-compatible but actually rely on bash features.


That's a very odd way of doing it. Here's a better solution:
restart () { (pkill "$1" sleep 1 "$@") &}
I used "$@" instead of "$1" so you can pass arguments. It gets expanded to all arguments you gave the function.

You absolutely don't need a sh -c construction here, but occasionally it's useful. If so, you can use "eval" instead. It's a shell built-in.

Maybe you didn't read well, I said posh. I know well that bash isn't limited to POSIX nor fast. Anyway, I'm testing using dash at the moment.

I was replying to "Why does Debian have two shells that are sypposedly POSIX?".

I'm obviously talking about posh and dash. Bash isn't made by or for Debian.

Wow, great explaination. Thanl you.

Use runit. pkill is a dangerous thing

Lennart plz

I need to learn more ASCII.

Back to the top with you.

...

flatten_tree.sh
#!/bin/shfind -type f | sed -e 's#^\./##' -e 's#.#\\&#g' -e 'p;s#[/]#_#g' | xargs -n2 mv --find -type d ! -path '.' -exec rmdir -- {} +

rar2zip.sh
#!/bin/shworkdir="$(mktemp -d)"pwd="$(pwd)"for i in "$@"do mv -- "$i" "$workdir" cd "$workdir" unrar x "$i" rm "$i" zip -r "$pwd/${i%.*}.zip" . find . ! -path '.' -prune -exec rm -rf -- {} + cd "$pwd"done

im-sigmo-scale()
im-sigmo-scale(){ if [ $# -ne 3 ] || [ "$1" = "-h" ] then printf "Usage: %s input output geometry\n" "$(basename $0)" return 1 fi convert +sigmoidal-contrast 5.0,50% -filter LanczosSharp -distort Resize "$3" \ -sigmoidal-contrast 5.0,50% -quality 100 "$1" "$2"}

fd() { path="$1" regex="$2" find "$path" -maxdepth 1 -type f -regex "$regex" \ -exec md5sum '{}' ';' \ | sort \ | uniq -w33 --all-repeated=separate}
finds duplicates based on md5
some may prefer using "iname" over "regex"

Get a load of this guy:

echo -ne "\033#8";X=`tput cols`;Y=`tput lines`;((a=$X/2));((b=$Y/2));d=1;while \case $d in 0)((a=a

Isn't it a bit too slow compared to fdupes?

the fuck is this doing

Now I have a challenge. How can I modify a global variable inside of a subshell made by piping into while?
The only way I found to do it is not using | while but IFS=$(printf '\n\b); for

Depends. fdupes doesn't compare files that don't have the same size, but after the md5sum it does a byte-by-byte check. The find monstrosity could be faster when almost all files are duplicates.

#!/bin/shif [ -z "$1" ] || [ "$1" = "-h" ]then printf 'Usage: %s gallery-url\n' "$0" exit 1fiuser_agent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0"name=$(printf '%s' "$1" | sed 's#.*/##')id=$(printf '%s' "$1" | sed 's#.*pictures/\([^/]*\)/.*#\1#')list=$(wget -qO- "imagefap.com/pictures/$id/?view=2" \ | grep -o 'fap.to/images/thumb/[^"]*' \ | tail -n +2 \ | sed 's#thumb#full#')wget --wait=1 -U "$user_agent" -nv -nc $list -P "$name"cd -- "$name"count=0ls -t | tac | while read -r ido count=$(($count+1)) mv -- "$i" "count.${i##*.}"done

Added the tail -n +2 to avoid downloading the user avatar. Added a user-agent since imagefap doesn't like wget/curl. Rename the files based on their mtime.
The only (BIG) problem remaining is that wget doesn't retry when getting a 503, which imagefap seems to be spamming randomly. Pretty annoying.

en.wikipedia.org/wiki/Langton's_ant

Another one from the same guy.

for((P=10**8,Q=P/100,X=320*Q/(`tput cols`-1),Y=210*Q/`tput lines`,y=-105*Q,v=-2\20*Q,x=v;y

Maybe a random wait can fix it?

This isn't entirely intentional, their server is getting fucked. I solved it simply by redoing until it's done (wget -nc is kool).
#!/bin/shif [ -z "$1" ] || [ "$1" = "-h" ]then printf 'Usage: %s gallery-url\n' "$0" exit 1fiuser_agent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0"name=$(echo "$1" | sed 's#.*/##')id=$(echo "$1" | sed 's#.*pictures/\([^/]*\)/.*#\1#')list=$(wget -qO- "imagefap.com/pictures/$id/?view=2" \ | grep -o 'fap.to/images/thumb/[^"]*' \ | tail -n +2 \ | sed 's#thumb#full#')while truedo wget_status="$(wget -U "$user_agent" -nv -nc $list -P "$name" 2>&1 | tee /dev/tty)" [ ! -z "$wget_status" ] || break printf '\033[28mReiterating to get all files\n\033[0m'

In the process, I made:
rename_mtime.sh
#!/bin/shcnt=0ls -tr | while read -r ido cnt=$(($cnt+1)) mv -- "$i" "$cnt.${i##*.}"done
and
loop()
loop(){ if [ $# -lt 2 ] || [ "$1" = "-h" ] then printf "Usage: %s command args...\n" "$(basename $0)" return 1 fi echo ${@:2} | xargs -n1 $1}
Now if someone can make this loop work with command and args, it'd be cool:
Basically, I'd want to be able to doloop "echo -n" a b cand getabc

You should quote more of your variables. Lots of unquoted variables in your definition of loop.
loop () { cmd=$1 shift for arg in "$@"; do $cmd "$arg" done}
I left $cmd unquoted because command names are unlikely to contain whitespace or glob characters, and passing extra arguments is very useful. It's acceptable in that case.

I realized my version wasn't working because of zsh. It works perfectly with sh.

Final version
#!/bin/shif [ -z "$1" ] || [ "$1" = "-h" ]then printf 'Usage: %s gallery-url\n' "$0" exit 1fiuser_agent="Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0"name=$(echo "$1" | sed 's#.*/##')id=$(echo "$1" | sed 's#.*pictures/\([^/]*\)/.*#\1#')list=$(wget -qO- "imagefap.com/pictures/$id/?view=2" \ | grep -o 'fap.to/images/thumb/[^"]*' \ | tail -n +2 \ | sed 's#thumb#full#')while [ ! -z "$(wget -U "$user_agent" -nv -nc $list -P "$name" 2>&1 | tee /dev/tty | grep -F 'ERROR 503')" ]do printf '\033[7mReiterating to get all files\n\033[0m'done

Thanks for project idea, I was bored. Just did it in few hours in C, using the rsync md5 file and the FNV32 hash. Now the "fun" part: use pthread to parallelize it kill me.

alias sudo='sudo '

Pretty useful to get autocompletition for sudo aswell.

bin/find-dups src/* *Skipped bin: not a regular file.Skipped include: not a regular file.Skipped src: not a regular file.Duplicate files: src/test, src/md5.c (md5sum: c54a41e1f99c649b12e0c0bdfac577a0)Duplicate files: test2, makefile (md5sum: 54a8959d7a31ba2d75e275d1cebc4)

xp() { xargs -n 1 -P 10}
Using this hack when parallel isn't available.
seq 10 | xp

zstyle ':completion:*:sudo:*' environ PATH="$SUDO_PATH:$PATH"
on zsh.

Some things to get some zsh functonality on bash.

1.)
bind '"\e[5~": history-search-backward'
bind '"\e[6~": history-search-forward'

Usage example:
Type "vim" and use PGUP/PGDWN to cycle through all previous vim commands in your history.

2.)
bind '"\e[Z": menu-complete'

Usage example:
Type part of a command and cycle through possible autocompletitions (like zsh) via SHIFT+TAB.

3.)
bind '"\em": "\eb\ed\C-y\e#man \C-y\C-m\C-p\C-p\C-a\C-d\C-e"

Usage example:
Quickly open the manpage for a command currently under your cursor (like zsh) without changing the cli via ALT+m.

Not portable. pubs.opengroup.org/onlinepubs/9699919799/
Just curl/wget parallel; it's just a perl script.

This is Tomb
dyne.org/software/tomb/
So, Tomb is really great. Thing is that is has a dependency on zsh, which I think is like 30 megs or something and not as available on as many systems as bash is. (All of them lol)
Is there anuthing about about Tomb that would prevent it's zsh code from being rewritten in bash?

You're retarded, aren't you? The right thing to do would be to rewrite it to be sh compatible (NetBSD's ash or Debian's dash being good to test this)

###################################################### Create box of '#' characters around given string. ######################################################box() { t="$1xxxx" c=${2:-#} echo ${t//?/$c} echo "$c $1 $c" echo ${t//?/$c}}
Can't remember where I found this. Doesn't work with multiple lines, any way to fix?

No. You need to quote redirections too. The shellcheck rule is there for a reason.

$ out='globs * ruining your shit'$ echo test > $outbash: $out: ambiguous redirect$ echo test > "$out"

Ohh. Okay.
There really should be a breif write up of what the fuck the differences are between all these shells and why they matter.

Shitty one-liner to scan a directory of youtube-dl downloads and print duplicate video IDs:
ls * | rev | cut -d. -f2 | cut -c1-11 | rev | sort | uniq -c | egrep -v '^\s+1'

$ printf 'The boxes package can do this.\nReally.' | boxes/**********************************//* The boxes package can do this. *//* Really. *//**********************************/

Poor man's macchanger:

macchanger() { rnd() { printf '%02x:%02x:%02x:%02x:%02x:%02x' \ $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)) \ $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)) } unset int; int="${1:-wlan0}" unset mac; mac="${2:-$(rnd)}" sudo true printf 'MAC (old): %s\n' "$(ip link show $int | awk '/^ / { print $2 }')" sudo ip link set dev "$int" down sudo ip link set dev "$int" address "$mac" sudo ip link set dev "$int" up printf 'MAC (new): %s\n' "$(ip link show $int | awk '/^ / { print $2 }')"}

Tried to recreate that Amiga/C64 "cracktro" effect. Had a hard time figuring out that I need to update lines and columns myself when changing the terminal size. Well, here's the result.

#!/usr/bin/env bash# GPLv3+do_int() { printf '\x1bc' exit 0}trap do_int SIGINTdo_winch() { lines="$(tput lines)" columns="$(tput cols)"}trap do_winch SIGWINCHdo_winchwhile :; do printf '\x1b[%s;1f\x1b[48;5;%sm%*s' \ "$((RANDOM%lines+1))" "$((RANDOM%${1:-8}))" "$columns"done

Works on my machine. I don't think that's POSIX.
$ touch 'a b' 'a c'$ f='a *'$ echo hi > $f$ lsa * a b a c

[ ! -z
Inverting test -z ...

Yes. Test if grep output isn't empty.

Your solution doesn't handle whitespaces (I hate xargs).
#!/bin/shif [ $# -lt 2 ]then printf 'Usage: %s command args...\n' "$(basename "$0")" exit 1ficmd="$1"shiftprintf '%s\n' "$@" | xargs -d '\n' -P$(nproc) -n1 $cmd
This does. Remember that xargs -P and -d is still not POSIX. Won't work on FBSD for example (not support for -d).

Have some ImageMagick.

termout() { test "$1" || { printf 'Usage: %s [cmd]\n' "$FUNCNAME" return 1 } bg='#111' fg='#ddd' fn='Liberation-Mono' ps='16' "$@" | \ convert -background "$bg" -fill "$fg" -font "$fn" -pointsize "$ps" label:@- \ -trim png:- \ | convert -border 10 -bordercolor "$bg" - png:- \ | convert - \( +clone -background "#000" -shadow 80x20+0+0 \) \ +swap -background none -layers merge +repage \ "imagemagick_$(date +%Y%m%d%H%M%S).png"}

$ termout apt-get moo

There's nothing complicated. You comply with pubs.opengroup.org/onlinepubs/9699919799/ and you'll never have any problems (except newlines in filenames).

Hopefully a wizard can help me out here.

I want to run a script as terminal screensaver, so I searched the web and found out that there's a variable called TMOUT, if set, it exits bash after N seconds without interaction. I tried TMOUT=3; trap 'myscript; bash' EXIT and it works. The problem: I'm loosing my session so maybe there's a less retarded solution? Perfet would be:

- Start shell, a function from ~/.bashrc waits for 5 minutes without interaction
- after 5 minutes, screen gets saved, myscript.sh starts
- hit a key, script stops (guess this could be dont with "read" in the script itself), screen gets restored
- timeout starts over

If you can't find a better solution I recommend replacing "bash" by "exec bash". That way you replace the process and don't get a whole string of processes waiting for each other to exit before exiting.

Just made something to merge multiple zip archives into one while preserving file order (made for mango chapters -> volume)
#!/bin/shif [ $# -lt 3 ] || [ "$1" = "-h" ]then printf "Usage: %s output archives...\n" "$0" exit 1fioutput="$1"shiftworkdir="$(mktemp -d)"pwd="$(pwd)"for i in "$@"do mkdir "$workdir/$i" unzip "$i" -d "$workdir/$i"donecd "$workdir"zip -r "$pwd/$output" .rm -rf "$workdir"

#!/bin/sh# Dependency: GNU or *BSD xargs# Use the GNU parallel perl script instead if you want a robust solutionif [ $# -lt 2 ]then printf 'Usage: %s command args...\n' "$0" exit 1ficmd="$1"shiftprintf '%s\0' "$@" | xargs -0 -P$(nproc) -n1 $cmd
Still not POSIX but I'm at least portable between GNU and {Dragonfly,Free,Net,Open}BSD now.

xkcdpw() { LC_ALL=C grep '^[a-z]\+$' /usr/share/dict/words \ | shuf --random-source=/dev/urandom -n 4 \ | paste -s -d-}

Check out my shell scripts:

42xlyaqlurifvvtq.onion/endware/
42xlyaqlurifvvtq.onion

endwall.sh - an iptables based firewall script
endsets.sh - an ipset based blacklisting script
endlists.sh - an iptables based blacklisting script
endloads.sh - a wget downloader with random user agent
endtube.sh - a youtube-dl video downloader with random user agent
endnode.sh - check your tor exit node in the command line
alogz- an apache web server log reader
mlogz - a postfix mail log reader
spamlogz - a log reader for blacklisted ips flagged in endwall, endsets and endlists
pdfclean.sh - a pdf exif, and javascript remover
safedown.sh - download files into a jail
safemode.sh - enter the jail
passgen.sh - generate a random password
renum.sh - rename files sequentially or randomly by sequential numbering
rmdupes.sh - remove duplicate files by md5
proxyload.sh - download a list of socks5 and http proxies
proxycheck.sh - scrape the proxies and compile a list of working proxies
endcurl.sh - random user agent curl with tor
endget.sh - random user agent wget with tor
endtorrc - a torrc-defaults file
check16.sh - check a /16 cidr range with geoip
check8.sh - check a /8 cidr range with geoip
iplookup.py - a geoiplookup script
endmail.sh - send mail to a tor hidden service mail server
endfix.cf - a postfix main.cf configuration file for tor hidden service mail servers.

Leave comments and requests for more products in my thread on endchan.xyz.
endchan5doxvprs5.onion/os/

Thanks.

Faggotnigger here. I've been using linux as my daily driver for ~1 year now, but I still don't know how to do any scripting at all.

Do you guys have any good learning resources that you'd recommend? I'm comfortable with the terminal and can use a computer without a keyboard, and I'm at the point where I could actually benefit a great deal by learning how to write simple scripts for myself, so I don't have to do everything manually.

A shell script is terminal commands (shell commands, technically) in a text file. Just put them in a file, line by line. You can either execute the file with "bash " (assuming you wrote it for bash) or by making the first line "#!/bin/bash" and making the file executable.

How advanced is your terminal usage? Do you know how to use variables? How about for loops?

When you run a shell script you can access the first argument with "$1", the second argument with "$2", etcetera. You can get all arguments at once with "$@".

Shell scripting is great for automating tasks, but not so great for most other things and for "real programming". I recommend learning Python as well for a more conventional programming language.

I'll post some books. The only one of them I've read is Think Python, which was good as far as I remember.

...

...

You read tldp.org/LDP/abs/html/ then wiki.ubuntu.com/DashAsBinSh

For you poor bastards out there stuck scripting in Windows, batch is the only alternative to this retarded OOP scripting language. It works out of the box and with no hoops to jump through. Just takes some work that is taken for granted everywhere else.

@echo off:: common.bat:function_opecho OP is a faggoto:eof

@echo off:: main.bat:mainecho [email protected]/* */ off> main_combined.batecho goto:main_combined>main_combined.batecho.>main_combined.bat:: this can allow you to override labels found in common.bat, first parsed first servedif exist C:\Scripts\common.bat type C:\Scripts\common.bat > main_combined.battype common.bat > main_combined.batecho.> main_combined.battype main.bat > main_combined.batcall main_combined.bat %1:main_combinedverify >nulcall:function_%1if errorlevel 1 echo try calling main.bat OPgoto:eof

For anything more than simple stuff, use python.

You can use eshell :^)

I'm not very skilled. When I said I'm comfortable using the terminal, I just mean that. In a literal sense. Using a terminal is not scary to me.

I'm not trying to learn real programming. Automating basic tasks is all I want to learn. My chosen field and profession has nothing to do with tech. I just want to become better at using my computer effectively, and maybe learn a bit more about how it works.

Thank you for the resources.

Well what kind of basic tasks did you have in mind? Keep in mind that something that's easily done in the UI can be difficult to translate to the commandline as it's custom tailored towards a specific behavior and outcome. That said, there are a ton more things that can be done with scripting that would be really burdensome to provide through the UI.

Good thread.

I just discovered that cd - returns to the previous dir. A bit like a pushd/popd with a single entry.

This is barp, there are many like it but this one is mine.

barp() { b="█" a="" r="▒" p=" " [ "$1" -ge 10 ] && p="$b$a$r$a$r$a$r$a$r$a$r$a$r$a$r$a$r$a$r$a" [ "$1" -ge 20 ] && p="$b$a$b$a$r$a$r$a$r$a$r$a$r$a$r$a$r$a$r$a" [ "$1" -ge 30 ] && p="$b$a$b$a$b$a$r$a$r$a$r$a$r$a$r$a$r$a$r$a" [ "$1" -ge 40 ] && p="$b$a$b$a$b$a$b$a$r$a$r$a$r$a$r$a$r$a$r$a" [ "$1" -ge 50 ] && p="$b$a$b$a$b$a$b$a$b$a$r$a$r$a$r$a$r$a$r$a" [ "$1" -ge 60 ] && p="$b$a$b$a$b$a$b$a$b$a$b$a$r$a$r$a$r$a$r$a" [ "$1" -ge 70 ] && p="$b$a$b$a$b$a$b$a$b$a$b$a$b$a$r$a$r$a$r$a" [ "$1" -ge 80 ] && p="$b$a$b$a$b$a$b$a$b$a$b$a$b$a$b$a$r$a$r$a" [ "$1" -ge 90 ] && p="$b$a$b$a$b$a$b$a$b$a$b$a$b$a$b$a$b$a$r$a" [ "$1" -ge 100 ] && p="$b$a$b$a$b$a$b$a$b$a$b$a$b$a$b$a$b$a$b$a" printf '%s\n' "$p"}
$ barp 25
██▒▒▒▒▒▒▒▒
$ barp 75
███████▒▒▒

This one is basically copy paste from the sox manpage, but pretty useful (for tuning music instruments).

for n in E2 A2 D3 G3 B3 E4; do play -n synth 4 pluck $n repeat 2; done

barp () { b="█" a="" r="▒" p=10 while [ "$p" -le "$1" ]; do printf '%s' "$b$a" p=$((p + 10)) done while [ "$p" -lt 100 ]; do printf '%s' "$r$a" p=$((p + 10)) done printf '\n'}

Ok, here's my favorite script (firefox.sh).

#!/bin/shxmessage -buttons "Cancel!":0,"Retreat!":0,"Bail out!":0,"Cover me! I'm going in!:1" -center \' ========================= W A R N I N G Firefox is a resource pig ========================= 'test $? -eq 0 && exit 0export HOME=/tmpcdfirefox -width 800 -height 600 -setDefaultBrowser -geometry +0+0

Beautiful. Added to my fortunes: Don't print; genrate. Thanks.

Added some shit here and turned it into a function.

bashtro() { [ "$1" = "-?" ] && { printf 'Usage: %s [NUMCOLORS] [NUMLOOPS]\n' "$FUNCNAME" return 0 } nc="${1:-8}" nl="${2:-10000}" # Save screen. printf \\x1b[?47h for ((i=0; i

pipes() { declare -i f=75 s=13 r=2000 t=0 c=1 n=0 l=0 declare -ir w=$(tput cols) h=$(tput lines) declare -i x=$((w/2)) y=$((h/2)) declare -ar v=( [00]="\x82" [01]="\x8c" [03]="\x90" [10]="\x98" [11]="\x80" [12]="\x90" [21]="\x94" [22]="\x82" [23]="\x98" [30]="\x94" [32]="\x8c" [33]="\x80" ) tput smcup tput reset tput civis quit(){ tput rmcup; tput reset; break; } while :; do read -s -n 1 -t $(printf "scale=5;1/$f\n" | bc) && quit (($l%2)) && ((x+=($l==1)?1:-1)) ((!($l%2))) && ((y+=($l==2)?1:-1)) ((c=($x>$w || $x$h || $y$w)?0:(($x$h)?0:(($y1||$n==0)?$l:$l+$n)) ((n=($n$r)) && tput reset && tput civis && t=0 || ((t++)) l=$n done}

+not mine tbh

Bump while waiting to see if my survived the server timing out.

bump

Could someone please share a bash script for downloading all images (full size) from a given thread on Holla Forums?

Thank you!

#!/bin/shexec wget -e robots=off -r -nd -nc -I '*/src' -R '*.html' -H -- "$@"

Thank you!

Thank you! Works perfectly as expected from Holla Forums!

why

shorter:

wget -re robots=off -nd -HIsrc -nc -Rhtml

Because the shell process is no longer needed.

I didn't want to download a complete git repo, only a single fonts directory, so I did this:
git-pick() { svn co $(sed 's/tree\/master/trunk/'

Doesn't it die when the script's finished anyway?

Question: What is the prefered way to do it?

for i in {1..10}; do printf '%d\n' "$i"; done

for i in $(seq 10); do printf '%d\n' "$i"; done

for ((i=1; i

I know this isn't directly related to the thread.
I'l post this anyway because I want to share my freind's really effective work.
spit.mixtape.moe/view/9ee7a585

As it turns out, even with just the script the body was too long causing posting to timeout.
I know this isn't directly related to the thread.
I'l post this anyway because I want to share my freind's really effective work.
spit.mixtape.moe/view/9ee7a585

Sure, but it takes up some resources before that point.


The first one is the clearest. It only works in shells that support it, like bash and zsh. If you're explicitly using one of those and the number isn't insanely large it's fine. But for {1..100000} it has to expand it to 100000 strings before it can continue, which takes a while.

The second one relies on seq, which is not part of POSIX and can't always be relied on to exist. But it works with POSIX sh, so you don't need to depend on bash or zsh any more if you do that. For this particular example you could just run "seq 10" instead, by the way, you don't need a loop.

The third one doesn't work in all versions of sh. If you're explicitly using bash or zsh it's fine, especially for counting up to large numbers because it doesn't have the performance problem of the first two.

The fourth one is pure POSIX sh that doesn't depend on weird external tools like seq. It's the best option if you're not explicitly writing bash or zsh.

How do I read from user input multiple lines in posix read?
non posix i can just change the delimiter with read -d"~" but -d doesn't work in dash.

read inside infinite loop
break when $? is non-zero

trap "printf '\033[38;5;29m>implying %d\033[m\n' $?" ERR

Hide an image in the low bits of another.

#!/usr/bin/env bashif [[ "$1" == "-h" ]]; then convert "$2" "$3" -fx '(((u*255)-(u*255)%4))/255+v/85' "$4"elif [[ "$1" == "-s" ]]; then convert "$2" -fx '((u*255) % 4)/3' "$3"fi

./hide.sh -h cover.png secret.png hidden.png
The cover and secret should have the same size, and the output can't be jpg or some other lossy format.

./hide.sh -s hidden.png revealed.png
to reveal it again.

Breddy cool, but I guess you don't need bash here, #!/bin/sh should be enough.
#!/bin/shif [ "$1" = "-h" ]; then convert "$2" "$3" -fx '(((u*255)-(u*255)%4))/255+v/85' "$4"elif [ "$1" = "-s" ]; then convert "$2" -fx '((u*255) % 4)/3' "$3"fi

By the way, check out: imagemagick.org/script/cipher.php maybe you want to combine it.

Wouldn't that also work with cat? I remember when people added archives to images and you basically just extract the images as archives to get the contents.

#!/usr/bin/env bashon="◼"off="◻"colornum=27colorinfo=237format() { sed " s/1/$on/g s/0/$off/g s/\s*/ /g "}sigint() { tput reset break}trap sigint SIGINTsigwinch() { tput clear cols=$(tput cols) lines=$(tput lines) numcols=$(((cols-16)/2)) numlines=$(((lines-6)/2))}trap sigwinch SIGWINCHsigwinchtput civiswhile :; do h=$(date +%H) m=$(date +%M) s=$(date +%S) h_binary=$(printf 'obase=2;%d\n' "${h#0}" | bc) m_binary=$(printf 'obase=2;%d\n' "${m#0}" | bc) s_binary=$(printf 'obase=2;%d\n' "${s#0}" | bc) tput cup $numlines $numcols tput setaf $colorinfo printf '%02d' "${h#0}" tput setaf $colornum printf '%06d' "${h_binary#0}" | format tput cup $((numlines+2)) $numcols tput setaf $colorinfo printf '%02d' "${m#0}" tput setaf $colornum printf '%06d' "${m_binary#0}" | format tput cup $((numlines+4)) $numcols tput setaf $colorinfo printf '%02d' "${s#0}" tput setaf $colornum printf '%06d' "${s_binary#0}" | format tput cup $((numlines+6)) $numcols tput setaf $colorinfo printf ' 32 16 8 4 2 1' read -n 1 -t 1 && sigintdone

The cat version is easier to find if you don't already know it's there, and it's automatically stripped off on Holla Forums nowadays.

How do I make this POSIX?
shuf --input-range=$(date -r "$file" +%s000)-$(date +%s999) -n1

Basically its function is to output a number between the file's last modification date + 000 and the current date + 999 (to create an 'anonymized' imageboard filename)
Every single component of it is non portable

shuf is coreutils
according to pubs.opengroup.org/onlinepubs/9699919799/utilities/date.html
date -r isn't posix
date +%s isn't posix either. solution: awk 'BEGIN{srand();print srand()"000"}'

Lower Range: date -r -> /
Upper Range: date +%s -> awk 'BEGIN{srand();print srand()"000"}'
Shuffle num: shuf --input-range=$(date -r "$file" +%s000)-$(date +%s000) -n1 -> awk -v min="$lowerRange" -v max="$upperRange" 'BEGIN{srand(); print int(min+rand()*(max-min+1))}' + awk -v min="$lowerRange" -v max="$upperRange" 'BEGIN{srand(); printf("%03d" ,min+rand()*(max-min+1))}'


Working with digits 13 characters long stuffed up in awk, for me. it turns them in to 1.030e+2 and even if i printf "%f" them it's limited because of the limits of srand or rand in awk. some shit like that.

I read there's no posix way to find file modification date so i could just do an if elif for each major way of finding file modification date and the last else being just finding current epoch time and taking away a years worth of seconds to find my lower range as an alternative (i believe the 4chanx randomize filename option does that)?

Sorry for the second awk in the shuf replacement it's min=000 max=999 to create a random 3 digit number to append to the 10 digit number.

I guess the sanest solution here would be a userscript (maybe some kind Holla Forumsnican will make this happen?). That said, just imagine 'modification' also includes changing the filename, with this in mind, just rename your files to date +%s%3N and stop hurting yourself.

Not mine, but leaving this here since it's the most matrix-ish script I know about.

I wanted to have it as function for my bashrc, so I subshell'd the loop to silence the background jobs.

Original (from bruxy.regnet.cz/web/linux/EN/matrix-sh/):
#!/bin/bashecho -e "\033[2J\033[?25l"; R=`tput lines` C=`tput cols`;: $[R--] ; while true do ( e=echo\ -e s=sleep j=$[RANDOM%C] d=$[RANDOM%R];for i in `eval $e {1..$R}`;do c=`printf '\\\\0%o' $[RANDOM%57+33]` ### bruxy.regnet.cz/web/linux ###$e "\033[$[i-1];${j}H\033[32m$c\033[$i;${j}H\033[37m"$c; $s 0.1;if [ $i -ge $d ]then $e "\033[$[i-d];${j}H ";fi;done;for i in `eval $e {$[i-d]..$R}`; #[mat!rix]do echo -e "\033[$i;${j}f ";$s 0.1;done)& sleep 0.05;done #(c) 2011 -- [ BruXy ]

Subshell'd:
matrix() {echo -e "\033[2J\033[?25l"; R=`tput lines` C=`tput cols`;: $[R--] ; while true do (( e=echo\ -e s=sleep j=$[RANDOM%C] d=$[RANDOM%R];for i in `eval $e {1..$R}`;do c=`printf '\\\\0%o' $[RANDOM%57+33]` ### bruxy.regnet.cz/web/linux ###$e "\033[$[i-1];${j}H\033[32m$c\033[$i;${j}H\033[37m"$c; $s 0.1;if [ $i -ge $d ]then echo -e "\033[$[i-d];${j}H "; fi; done; for i in `eval $e {$[i-d]..$R}`; doecho -e "\033[$i;${j}f ";$s 0.1;done)& disown); sleep 0.05;done # (c) 2011 BruXy}

The only flaw is that I don't know how to reset the terminal to it's previous state. I tried a SIGINT trap, but it looks like the script works asyncronous by creating millions of jobs and I don't know how to kill them all at once (so one could add a tput reset; return afterwards).

Well, enjoy.

Slapped together a little something to move files from one folder to two other folders.
Reason: I save shit to ~/Downloads, if I want to keep it, it is supposed to go into ~/Pictures as well as a thumbstick

#!/usr/bin/env bashoptimize(){ local png=$1 optipng --quiet $png}CORES=2FILETYPES=(png webm gif jpg)SOURCEDIR="$1"TARGETDIR="$2"TARGETTWO="$3"PNGS="$SOURCEDIR"/*.pngCOUNTPNG=$(ls $PNGS 2>/dev/null | wc -l)#optimize pngs#if [ "$COUNTPNG" -gt 0 ] then echo "Optimizing "$COUNTPNG" pngs." for PNG in $PNGS; do ((i=i%($CORES+1))); ((i++==0)) && wait optimize "$PNG" & done wait#fi#move files to targetsfor EXT in "${FILETYPES[@]}"; do rsync -qauzP --ignore-missing-args "$SOURCEDIR"/*."$EXT" "$TARGETDIR"/ rsync -qauzP --ignore-missing-args --remove-source-files "$SOURCEDIR"/*."$EXT" "$TARGETTWO"/doneexit 0
obviously, there's much to iron out
though for now I am annoyed at the if clause not working because of "unexpected token fi". Yea, 'fi' is highly unexpected after 'if'
also, running shit parallel is annoying with bash; seriously considering to rewrite it all in perl or something

...

...

ebin

imagemagick?

I was bored so I made this thingy to set weather related wallpapers (maybe as cron job). It's using the output of wttr.in, which gets your location based on your ip, but you can also set your own like wttr.in/moon.

#!/usr/bin/env bashweather=$(curl -s wttr.in | sed '3!d')wallpapers="$HOME/wallpapers/weather"command="feh --bg-fill"if grep -qi "clear"

Bumping with the most silly script I ever made. `funame' spoofs uname. make a backup of uname (uname.bak) and replace it with this script to spoof results to programs that use the output of uname (replace the variable on the top to your likings, defaults are uname's default output).

#!/bin/shs="$(/bin/uname.bak -s)"n="$(/bin/uname.bak -n)"r="$(/bin/uname.bak -r)"v="$(/bin/uname.bak -v)"m="$(/bin/uname.bak -m)"p="$(/bin/uname.bak -p)"i="$(/bin/uname.bak -i)"o="$(/bin/uname.bak -o)"args="$*"[ "$args" ] || { printf '%s\n' "$s" && exit}for i in $args; do case "$i" in -a|--all) printf '%s ' "$s $n $r $v $m $p $i $o" ;; -s|--kernel-name) printf '%s ' "$s" ;; -n|--n) printf '%s ' "$n" ;; -r|--kernel-release) printf '%s ' "$r" ;; -v|--kernel-version) printf '%s ' "$v" ;; -m|--m) printf '%s ' "$m" ;; -p|--p) printf '%s ' "$p" ;; -i|--hardware-platform) printf '%s ' "$i" ;; -o|--operating-system) printf '%s ' "$o" ;; --help) /bin/uname --help exit 0 ;; --version) /bin/uname.bak --version exit 0 ;; esacdoneprintf '\n'

Now you can do two amazing things: Tell programs like screenfetch that you're running Windows 95 and be cool on the internet and basically fuck up your system completly. Nice? Nice!

Oh, --help should also point to /bin/uname.bak

if this


is this

I'm requsting sauce.

since apparently getopts can't deal with options getting multiple parameters, I'm trying to write an alternative that can handle just that
results are kinda wonky for now

get_options(){ while :; do case $1 in -h|-\?|--help) show_help exit ;; -s|--source|--sources) #count the number of source folders i=0 shift for dir in $@; do if [ -d "$dir" ]; then SOURCES+=("$dir") i=$((i+1)) shift else #check if the non-directory is a parameter first=${dir:0:1} if [ $first = "-" ]; then break else echo $dir is not a directory, skipping fi fi done if [ $i -lt 1 ]; then printf "ERROR: '--source' requires a directory as argument\n" >&2 exit 1 fi echo "-s is done, the sources are: ${SOURCES[@]}" ;; -t|--target|--targets) #count the number of target folders i=0 shift for dir in $@; do if [ -d "$dir" ]; then TARGETS+=("$dir") i=$((i+1)) shift else #check if the non-directory is a parameter first=${dir:0:1} if [ $first = "-" ]; then break else echo $dir is not a directory, skipping fi fi done if [ $i -lt 1 ]; then printf "ERROR: '--target' requires a directory as argument\n" >&2 exit 1 fi echo "-t is done, the targets are: ${TARGETS[@]}" ;; --) shift break ;; -?*) printf "WARN: Unknown option (ignored): %s\n" $1 >&2 ;; *) #default case, no more options break esac shift done}

"m" is a new command line utility for the GNU bash shell, made by the well known hacker Anonymous. It works like "man", but will ask bash's builtin "help" program in case "man" can't deliver. With only 7 LOC and a short command name, "m" follows the KISS philosophy, which even pleases beardest UNIX wizards. And the best of all: It's licenced under the GNU PUBLIC LICENCE Version 3 or later. Buy "m" - where freedom meets elegance.

m() { man "$@" [ $? = 16 ] && { printf '... calling help.\n' help "$@" }}

Fail.

Oh boy, fizzbuzz!
#!/bin/kshfor i in {1..100}; do if [ $((i % 15)) -eq 0 ]; then echo "fizzbuzz" elif [ $((i % 5)) -eq 0 ]; then echo "buzz" elif [ $((i % 3)) -eq 0 ]; then echo "fizz" else echo ${i} fidone

a few months ago an user posted a glitch gif makes script, does anyone happen to have it?

Lost it too, at this point I wish'd we had an archive.

I`l dig through my copies of previous bash scripting threads when I have a chance.

#!/usr/bin/env bashmyself="$(basename "$0")"if [[ $# -lt 4 ]]; then printf 'Usage: %s [source] [frames] [delay] [resize]\n' "$myself" printf 'Example: %s pic.jpg 50 10 320\n' "$myself" exit 0fi# This method works best with the JPEG format.convert "$1" /tmp/ggf.jpg# Create frame copies.for i in $(seq "$2"); do cp "/tmp/ggf.jpg" "/tmp/ggf-${i}.jpg" # Poor man's data bending using sed. # Different settings = different glitches. sed -i "s/$((RANDOM%14))/1001/g" "/tmp/ggf-${i}.jpg" printf '\rGlitching frame %s/%s ... ' "$i" "$2"doneprintf '\nAnimating ... 'convert \ -delay "$3" \ -resize "$4" \ /tmp/ggf* "${1}_glitched_$(date +%s%3N).gif" \ 2>/dev/nullprintf '\nCleanup ... \n'rm /tmp/ggf*

awesome

m(){ man "$@" 2>/dev/null || help "$@" | less; }

I recently wrote a really basic script for managing oneliners.

It looks looks like this:

#!/bin/shdoc="$(cat

user here who wrote this thingy, if there's interest, I'd improve it with better code and more glitch modes.

#!/bin/bashwhile read input; do unixTime=$(stat -c %Y "$input")$[RANDOM % 9]$[RANDOM % 9]$[RANDOM % 9] ext="${input##*.}" cp "$input" "$unixTime.$ext"done
Made a script to change filenames back to Unix time because fuck sorting the new filenames. I originally used cp when I was testing the script but mv should be fine to use. I feel like this could be simplified though.

Neat, though it seems like some images just work better than others for this. (Does an image need more variety in colors for it to get the full effect?)

Thank you. Portability is nice.

#!/bin/sh

#set the keyboard backlight obsd (Apple Macbook Pro (8,2))
#see wsconsctl(8) and ascm(4)
echo -n "keyboard backlight percentage? > "
read percent
wsconsctl keyboard.backlight=$percent

lol formatting
#!/bin/sh#depends on maim and slop #make a dir named Screenshots in your /home/ maim -s -c 1,0,0,0.6 ~/Screenshots/$(date +%F-%T).png

Stupid question : I've a sdf.org account, my shell isn't responsive at all, this is mostly because I'm in EU and server is US, but which shell should I get for better performances ? ksh, bash or sh ?

They were written in a simpler time before the file names changed. I don't know enough wget to fix them. You could use this instead (python, not shell):
gitgud.io/ring/infinityctl
With a command like "infinityctl scrape tech 597990" it downloads all of a thread's files. If files have the deduplicated hash names it fakes the old-style unix time filenames instead.[...]Saving media.8ch.net/tech/src/1472080974290.gif to 1472080974290.gif...Saving media.8ch.net/file_store/bbb09c6811e48229599505ea136f6c6461ebf39c88924086fe0db022f0629228.jpg to 1472585790000-0.jpg...[...]You can also tell it to not replace hashes with -m plain or to save as the original names with -m original.

It does things in dumb ways for now. If a file already exists it'll clobber it.

Thanks. I didn't want to look even more like a fool before trying to fix it myself but it didn't workout.

I'm not literate in bash. Can someone explain how I use this? I recognize the ffmpeg part, though what's weird to me is that the output looks to be an mkv rather than a webm. I also don't understand how to choose the video or thumbnail files or how to even run the script.

Updating what I said in thanks once again it is seems to be working quite well.

dash/ash, obviously.

sh might have very small latency improvements over the others, but don't count on it.

See if you can connect to it using mosh. It's a wrapper around ssh that predicts the server output to make typing feel faster.

I use mpeg2video (because it has fast encoder) in the mkv container as an intermediate format to avoid having to deal with appropriate bitrate/encoder/[...] in this script. You have to re-encode it afterwards.

Or you could modify it and make it directly produce a webm, specifying appropriate bitrate and all that stuff. You have duration, width and height right there... though having to fit in the file limit, you'll probably want to do a two pass encode.

As for how to use it, that's in the "usage" function, it should be pretty straight forward. (the bit at the bottom that makes the -e switch work is commented out, because it relies on other script of mine, so that does not work)

Yeah, I just put it everywhere out of habit, just to be safe.
>since your using bash you should use ${sar/:/\/} instead of sar=`tr ':' '/'