Bash Script

Post Your Bash Scripts
God helps those who help themselves, Holla Forums helps everyone else.

Other urls found in this thread:, agent



#!/bin/bashfor i in {1..500}; do echo -n "OP SUCKS COCKS " >&2done#sage


If your using bash brace expansion you do not need a loop for that
echo 'OP SUCKS COCKS'$v{1..500} >&2

That doesn't work if v1..500 is defined, I guess you can also take care of that though.


unset -v v{1..500}

What are the best books for learning bash? And while I'm at it is there any point in learning perl?

Learn bash with then unlearn it with, and
I'd say you learn Perl when you can't do it in sh (and I said sh), because Perl 5 is a wider standard than POSIX sh.

Found the underage faggot

Mastering UNIX Shel Scripting, Second Edition by Randal K. Michael (Wiley) is BY FAR the best book on shell scripting ever written.

As for Perl, there's Chromatic's Modern Perl 4th ed, but some people swear by Tim Maher's Minimal Perl for UNIX and Linux People, which is more sysadmin focused.

Also O'Reilly just published the 7th Edition of Learning Perl a few days ago.

Some script I made:
A sxiv+sh script based manga reader:
Some zsh functions and aliases:

Can someone make me a script that would grab manga off of kissmanga?

man wget

Doesn't work, I've tried.

Maybe you should install wget to get its man page.

No I mean i cant get anything off of kissmanga with wget.

I had made a (python) script for that but haven't updated it in years and it doesn't work anymore. The trick is to change your user-agent (for some retarded reason your browser tells the server its name). If you go to agent on your browser it should tell you its user-agent. If you try to get that page through wget you'll see the user-agent is different. Change wget's user-agent so it pretends to be a normal browser and it should work. If it still doesn't, try to use cookies.

To add on to this, you can change your user agent with the -U flag. Adding-U "definitely a real human being"to the command works on a surprising number of sites.

Is there a way to request a cookie? I would just want a script that works where I don't have to change something each time. Also could you tell me how to get the recursive part to just grab for one manga?

"give a man a fish and you feed him for a day; teach a man to fish and you feed him for a lifetime"

Exactly, I want to learn how to catch fish, not whales, dolphins, tuna, mermaids and every other fucking sea creature. I just need to know how to grab some manga off of a website.

So you read the man page of wget and you figure it out. And if your website is too complex for wget (which I doubt) you learn httrack.

Not everyone feels like joining a sekret club just to look at some chinese pictures.


Found the underage faggot

Yeah, that retarded reason that helps websites work. Fucking retards.

The user agent only ever helped websites work during the times when browsers were different. At this point its useless.

Yeah you're right. It's fucking useless. Let's make all computers use the same user agent and start seeing complaints from Firefox users not being able to view webp images, Safari not being able to do dick, IE being retarded as usual, and a fuckton of other problems.

It does. It was first standardized in POSIX.2: Shell and Utilities (IEEE Std 1003.2-1992)

Here's the latest revision (IEEE Std 1003.1-2008, 2016 Edition)

Sounds like the internet as usual to me.


Opera seems to work fine considering its using firefoxs user agent.

Dude. I'm not against you. I'd love it if browser differences suddenly ceased to exist, if Google suddenly stopped being piece of shit pressing jew niggers that force their stupid NIH syndrome down the entire Internet's throats, if Firefox fired all their SJW employes and got actual devs and engineers to work on their browser, and many other things. But the reality is browsers still have differences. Much minor than before, mind you, but the compatibility is still not perfect.
You might not see issues in a couple of hours, or hell, maybe a couple of days of browsing, and possibly never if you only ever visit a handful of sites. But some things are not going to work too well in some corner cases and specific scenarios. That's where the user agent string comes in handy.
Do I want it to be needed? No. Fuck that. But is what it is.


From that page:
On some implementations this might return:

Nobody said POSIX "/bin/sh". You're just being dense on purpose, nigger.

Whoops, he actually did. You're still trying to ruse.

Even Microsoft gets this right. Microsoft.

That's the most sensible reason I can think of for saying that POSIX doesn't standardise /bin/sh. I made but not .

fucking jews

Is there even that much of a difference?

You kidding, m8. See

the morals of aesop's fables aren't bible verses you retard
sage for off-topic

What's wrong with that?

I would expect a browser that targets homosexuals to have basic dick-handling capabilities


curl $1 | grep -o ',"[0-9]\{5,10\}":' | sort -u > 4chandlfileslolwtf
grep -o "[0-9]\{5,15\}" 4chandlfileslolwtf > filter4chandl
rm 4chandlfileslolwtf
echo $1 |grep -o "/.\{1,10\}/" > nameofboard
for thing in $(cat nameofboard)
for thread in $(cat filter4chandl)
echo $thread
echo "This program will now start to download the entire board"
sleep 10
curl ""$board"thread/"$thread | grep -o "\{1,25\}/[1-9][0-9]\{10,20\}\.[a-zA-Z0-9]\{2,10\}" | sort -u > my4chanfiles
wget -i my4chanfiles
rm my4chanfiles

oh hey der

Code is used with [code] [/code]

curl $1 | grep -o ',"[0-9]\{5,10\}":' | sort -u > 4chandlfileslolwtfgrep -o "[0-9]\{5,15\}" 4chandlfileslolwtf > filter4chandlrm 4chandlfileslolwtfecho $1 |grep -o "/.\{1,10\}/" > nameofboard for thing in $(cat nameofboard)do board=$thingdonefor thread in $(cat filter4chandl)do echo $thread echo "This program will now start to download the entire board" sleep 10 curl ""$board"thread/"$thread | grep -o "\{1,25\}/[1-9][0-9]\{10,20\}\.[a-zA-Z0-9]\{2,10\}" | sort -u > my4chanfiles wget -i my4chanfiles rm my4chanfiles done

Yeah, that's all I ever use when writing shell scripts, except some occasional times when I can be assured ksh is around.
Some years ago I had to clean up a clusterfuck of remote systems out in the field (spread out across all north america) and they weren't even guaranteed to be powered on at any given time. The machines ran various flavors of Linux, various distros and versions thereof. I ended up sticking as close as possible to POSIX /bin/sh and using only the arguments defined by POSIX for the various utilities (so no GNU extensions, etc.)
When I was satisfied it was solid enough (after testing), I deployed the script to a server it would get downloaded by all those systems and executed as part of a batch update process. Over the course of weeks, eventually it got run and everything worked perfectly. I also had the script send me emails with info and statistics about each system whenever that was possible. Some of the distros/versions reported were really ancient, like easily 10 years old. Someone who wrote naive version of this script would have assumed they all have recent version of bash, and used constructs that would have failed in the field, and there wasn't any easy way to get to those machines (just some clueless operators turned them on & off, to use them like any other appliance).
I don't even have bash installed on my OpenBSD machine. Never needed it.

Holla Forums's last shell script thread was 10/10, this one is basically /g/ tier.

What happend to this board?

Here's a oneline to download all images in a thread - might not work since the schema change

wget "$1" -N -e robots=off -r -nd -I '*/src' -R '*.html'

oh wait everything's changed completely... wtf codemonkey

strcmp() { [ "${1}" = "${2}" ]}strcpy() { eval "${1}=${2}"}strlen() { printf '%d\n' "${#1}"}
More like this?


Downloads the entire 4chan catalog
syntax is
./script [link to 4chan catalog]

for some reason it downloads duplicates of some images, try adding a unique only flag to wget

buttmad hilldoggs are sliding the site.

My music conversion script. Sh is a pain when you have to escape every fucking character.
#!/bin/sh# Needs: GNU/*BSD readlink (-f), GNU sed (-z), GNU/*BSD find (-print0)# imagemagick, GNU parallel, ffmpeg (with libvorbis)if [ $# -ne 1 ] || [ "$1" = "-h" ]then printf "Usage: %s directory\n" "$(basename "$0")" exit 1fibitrate="160k"cover_size="240x240"argfile="$(mktemp)"in="$(readlink -f -- "$1")"out="$(printf -- '%s (CONVERTED)\0' "$in" | sed -z 's#["\\\*\?|:]#_#g')"# Escape sed sensitive charactersvfat_pat='s#["\\\*\?|:]#_#g'path_pat="s#$(printf -- '%s\0' "$in" | sed -z 's#[]\#$*.^|[]#\\&#g')#\$(printf -- '%s\0' "$out" | sed -z 's/[\#&]/\\&/g')#"trap "rm -r -- \"$out\"; rm \"$argfile\"; exit" INT TERM HUP# Create empty arborescencefind "$in" -type d -links 2 -print0 | sed -z -e "$path_pat" \ -e 's#["\\\*\?|:]#_#g' | xargs -0 mkdir -p --# Copy and convert album artfind "$in" \( -type f -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' \ -o -iname '*.gif' \) -print0 | sed -z -e 'p' -e "$path_pat" \ -e 's#\(.*\)/[^/]*#\1/cover.jpg#' -e "$vfat_pat" | parallel -0 \ -n2 --eta --no-notice convert -thumbnail "$cover_size" -quality 95# Create argument file (why a file? to keep \0s)find "$in" -type f -name '*.flac' -print0 | sed -z -e 'p' -e 's#\.flac$#.ogg#' \ -e "$path_pat" -e "$vfat_pat" >"$argfile"parallel -0 -n2 --no-notice --eta --xapply \ ffmpeg -loglevel warning -threads 1 -i {1} -map 0:0 -c:a libvorbis \ -b:a "$bitrate" {2} :::: "$argfile"rm "$argfile"

Important question, by the way. How do you choose between POSIX and not failing on filenames with newlines in them?
I usually try to stay GNU/*BSD compliant, and disregard POSIX (not for sh, just the utils).

Some cleaning up.
#!/bin/sh# Needs: GNU/*BSD readlink (-f), GNU sed (-z), GNU/*BSD find (-print0)# imagemagick, GNU parallel, ffmpeg (with libvorbis)if [ $# -ne 1 ] || [ "$1" = "-h" ]then printf "Usage: %s directory\n" "$(basename "$0")" exit 1fibitrate="160k"cover_size="240x240"argfile="$(mktemp)"in="$(readlink -f -- "$1")"out="$(printf -- '%s (CONVERTED)\0' "$in" | sed -z 's#["\\\*\?|:]#_#g')"# Replace vfat illegal charactersvfat_pat='s#["\\\*\?|:]#_#g'# Escape sed sensitive characterspath_pat="s#$(printf -- '%s\0' "$in" | sed -z 's#[]\#$*.^|[]#\\&#g')#\$(printf -- '%s\0' "$out" | sed -z 's/[\#&]/\\&/g')#"trap "rm -r -- \"$out\"; rm \"$argfile\"; exit" INT TERM HUP# Create empty arborescencefind "$in" -type d -links 2 -print0 | sed -z -e "$path_pat" \ -e 's#["\\\*\?|:]#_#g' | xargs -0 mkdir -p --# Copy and convert album artfind "$in" \( -type f -iname 'folder.jpg' -o -iname 'folder.png' \) -print0 | \ sed -z -e 'p' -e "$path_pat" -e 's#/[^/]*$#/cover.jpg#' -e "$vfat_pat" | \ parallel -0n2 --eta --no-notice convert -thumbnail "$cover_size" -quality 95# Create argument file (why a file? to keep \0s)find "$in" -type f -name '*.flac' -print0 | sed -z -e 'p' -e 's#\.flac$#.ogg#' \ -e "$path_pat" -e "$vfat_pat" >"$argfile"parallel -0n2 --eta --no-notice \ ffmpeg -loglevel warning -threads 1 -i {1} -map 0:0 -c:a libvorbis \ -b:a "$bitrate" {2} :::: "$argfile"rm "$argfile"

God blesd this thread

that would make a great banner

I didn't know that newlines were a thing in file names. Why would somebody do that?

Because POSIX is retarded. Also, I decided to say fuck this shit because: newlines in filenames won't happen "on my machine" (tm) and because only GNU sed has the -z option.
#!/bin/sh# Needs: GNU/*BSD readlink (-f)# imagemagick, GNU parallel, ffmpeg (with libvorbis)if [ $# -ne 1 ] || [ "$1" = "-h" ]then printf "Usage: %s directory\n" "$(basename "$0")" exit 1fibitrate="160k"cover_size="240x240"in="$(readlink -f -- "$1")"out="$(printf -- '%s (CONVERTED)' "$in" | sed 's#["\\\*\?|:]#_#g')"# Replace vfat illegal charactersvfat_pat='s#["\\\*\?|:]#_#g'# Escape sed sensitive characterspath_pat="s#$(printf -- '%s' "$in" | sed 's#[]\#$*.^|[]#\\&#g')#\$(printf -- '%s' "$out" | sed 's/[\#&]/\\&/g')#"trap "rm -r -- \"$out\"; exit 1" INT TERM HUP# Create empty arborescencefind "$in" -type d -links 2 | sed -e "$path_pat" -e 's#["\\\*\?|:]#_#g' \ | xargs -d'\n' mkdir -p --# Copy and convert album artprintf '\033[1mConverting album art...\n\033[0m'find "$in" -type f -iname 'folder.jpg' -o -iname 'folder.png' | sed -e 'p' \ -e "$path_pat" -e 's#/[^/]*$#/cover.jpg#' -e "$vfat_pat" | \ parallel -n2 --no-notice convert -thumbnail "$cover_size" -quality 95parallel -n2 --eta --no-notice ffmpeg -loglevel warning -threads 1 -i {1} \ -map 0:0 -c:a libvorbis -b:a "$bitrate" {2} ::: \ "$(find "$in" -type f -name '*.flac' | sed -e 'p' -e 's#\.flac$#.ogg#' \ -e "$path_pat" -e "$vfat_pat")"

up() { [[ -z "${1}" ]] && return 1 complete -W "${PWD//// }" up cd "${PWD//$1*/$1}"}

I need a script that will extract all the archives in a folder (each with one file) and rename the extracted file to the name of the archive (minus file extension).
#!/bin/bashfor f in *.cdo echo "Processing $f file..." unzip $fdone

This is what I have so far, I just need to get the name of extracted file to rename it

#!/bin/bashfor f in *.cdo echo "Processing file $f" unzip -p "$f" > "${f/\.c/}"done

quick and dirty

for ip in 192.168.0.{1..254}; do ping -c 1 -W 1 $ip | grep "ttl="; done

#!/bin/bash# Scan local ips with ping; change network if necessaryfor ip in 192.168.0.{1..254}do ping -c 1 -W 1 $ip | grep "ttl="done

alias 'u'='du -hd1 | sort -hr'

I'd use a funtion so du can take arguments.

du() { du -hd1 "${@}" | sort -hr; }

Actually, don't do this; it will loop endlessly and crash your system.

du() { command du -hd 1 "${@}" | sort -hr; }

pull the grep out of the loop
for ... do ... done | grep

Hey shellfaggots, how do I rice my shell?

The Arch live ISO has a cool zsh terminal with colors and smiley faces and shit. But after I installed, I just get the boring old normal terminal. Best I could do is change font to Hack and use Solarized dark (which has a retarded normal text color by the way, I always switch it to white) on my xfce terminal.

zsh is a shell, not a terminal.
Why not copy the rc files you like from the Arch ISO?

That sounds like a solution but I was more looking for a nice guide explaining the interesting settings.

POSIX does not specify -d for xargs either, and it is less portable than -0. {Open,Free,Net}BSD have -0 but not -d, I don't know of anything other than GNU xargs that has -d.
Better to use find -exec than xargs for this, then you don't have to worry about newlines at all.
You don't need double quotes for variable assignments, a="$(b)" is the same as a=$(b). I wouldn't quote things like "160k"
You might want to trap EXIT instead of INT TERM HUP. I would use single quotes so you don't have to backslash escape, 'rm -r -- "$out"' instead of "rm -r -- \"$out\""
Don't embed escapes like '\033[1m' , use tput(1).

You can't do that and get around learning the shell. is a great resource.

I don't want to learn it, I just want it to look nice.

and thus oh-my-zsh was born

Don't listen to this guy, that's an awful book.
Useless uses of cat(1), dangerous lack of quoting for parameter expansions, incompatible code examples, code injection vulnerabilities, and tons of misleading examples. It does shit like tell you how to use the echo builtin safely in early chapters, and then doesn't follow its own advice for the rest of the book (correct solution: don't use echo, use printf).
GreyCat's wiki and the Bash Hackers wiki are the only reliably good resource for shell scripting. It is a waste of your time to read anything else. I'm not exaggerating or joking.
Yes, even the Advanced Bash Scripting guide is bad.

Forgot that.
Do it for syntax highlighting, actually.
Don't want to delete the result when exiting, m8...
The variables won't expand this way.
Thanks, didn't know about this one.

Yep, find(1)'s -exec option is the usual answer to this problem. The -z/-0/-d options for the builtins are not actually needed too much with careful use of it.
If you need to run actual shell script over the results of find(1) rather than just an existing binary, you can use sh(1) with a -c option as the argument to -exec:
$ find /foo/bar -type f -exec sh -c 'foo=$1 ; bar=${foo%.*} ; baz -- "$bar"' _ {} \;
That should work in a POSIXish environment, does not require Bash, and should handle even filenames with perverse characters like newlines in them.

The reason I mention the quoting is:
I did not notice that the variable expanded when the trap was set, you probably don't want it to, then you run into quoting problems. What if it is '$(rm -rf ~)'? Variables expand when the trap is run.

Use -exec '+' instead of ';' and iterate over the arguments, it will usually be faster as a new shell does not need to be executed for each file.
-exec sh -c 'for foo do bar=${foo%.*}; baz -- "$bar"; done' sh {} +

But that's the point. I want to delete these.

I don't understand what you mean.
It allows for code execution:
$ out='$(>file)'$ trap "echo rm -r -- \"$out\"" USR1$ ls # empty$ kill -s USR1 "$$"rm -r -- $ lsfile

Are you retarded? You're supposed to control what's inside the script. With you logic, we shouldn't use variable at all.
How am I supposed to do if the dir I want to delete has a dynamic name?

But the script sets it from $1, which is not being controlled from "inside the script".
trap 'rm -r -- "$out"' INT TERM HUP
will work for dynamic names

You call the script. It's not like I use this for CGI. Anyway, it's cleaner like this. Also, why is GNU sed the only one with -z? It's super useful.

Is it better to inizialize variables with var='' or unset var?

+ is not POSIX.

You dun goofed, crickey.

Fuck! I did! You are right!
Disregard that, I suck cocks
I noted its absence on my very old Debian machines and made the thoroughly wrong assumption it was specific to newer GNU find(1).

1. (This is the perfect prank script. For maximum lulz, enter it into the terminals of the Macs at an Apple Store.):
sleep 600; for (( i=10;;i+=10 )); do osascript -e "set volume output volume $i"; say penis; sleep 10; done;

2. (This script will make your Mac's terminal snow, and it looks best when entered in a terminal with white text on a black background.):
ruby -e 'C=`stty size`.scan(/\d+/)[1].to_i;S=["2743".to_i(16)].pack("U*");a={};puts "\033[2J";loop{a[rand(C)]=0;a.each{|x,o|;a[x]+=1;print "\033[#{o};#{x}H \033[#{a[x]};#{x}H#{S} \033[0;0H"};$stdout.flush;sleep 0.1}'


yes() { while :; do printf '%s\n' "${*:-y}" done}

You can't use ? as a flag in getopt.

fix it

What's all the optind stuff?

I'm not too good with bash stuff, but perhaps
while getopts ":ht:b:f:" opt; do case "$opt" in (h|\?) printf "Available options are:\n t - Top Text\n b - Bottom Text\n f - Path to image file - Mandatory!\n";exit 0;; (t) top_text="$OPTARG";; (b) bottom_text="$OPTARG" ;; (f) image_file="$OPTARG" ;; (:) printf "%s\\n" "Need an option for $OPTARG"; exit 1;; esacdone

if [ -z "$image_file" ] then echo "You must specify an image file. Use -h or -? for help."; exit 1fi
instead of -z which checks if the variable is set, do -f, which checks if the variable set/not set is an actual file.

if [ ! -f "$image_file" ]; then printf "You must specify an image file. Use -h for help.\n" exit 1fi

But that only checks if it's a valid file and not an image file. I suppose you could do a file mime type test with file -i -- "$image_file" ???