this post was submitted on 20 Jul 2023
4 points (83.3% liked)

Shell Scripting

1348 readers
3 users here now

From Ash, Bash and Csh to Xonsh, Ysh and Zsh; all shell languages are welcome here!

Rules:
  1. Follow Lemmy rules!
  2. Posts must relate to shell scripting. (See bottom of sidebar for more information.)
  3. Only make helpful replies to questions. This is not the place for low effort joke answers.
  4. No discussion about piracy or hacking.
  5. If you find a solution to your problem by other means, please take your time to write down the steps you used to solve your problem in the original post. You can potentially help others having the same problem!
  6. These rules will change as the community grows.

Keep posts about shell scripting! Here are some guidelines to help:


In general, if your submission text is primarily shell code, then it is welcome here!

founded 1 year ago
MODERATORS
 

cross-posted from: https://lemmy.world/post/1838642

link-batch is a minimalist script that generate symlinks from a list in a text file. Usage :

link-batch.zsh link-list.txt

where link-list.txt contains two columns : the first one for the links and the second one for the targets. Example :

~/.config/kitty	~/myfiles/config/kitty
~/.config/nvim	~/myfiles/config/neovim
~/.config/MuseScore	~/myfiles/config/MuseScore/$HOST
...

The two columns must be separated by a tab.

Shell vars like $HOME or $HOST are evaluated to their values.

Can be used to quickly deploy all home links in a fresh box.

top 1 comments
sorted by: hot top controversial new old
[–] gamma 1 points 1 year ago* (last edited 1 year ago)

Nice work! I would have done some things differently, but this is very readable.

Two recommendations for reading the file:

  • Use the (z) and (Q) flags so that instead of using tabs to separate the targets, simply quoting each argument works.
  • Instead of two independent lists, use an associative array with map[$link]=$target. Then you can check for duplicate links while reading the list.
linksfile=$1

typeset -gA linkmap

while read -r line
do
	# -- fields
	fields=(${(Q)${(z)line}})
	# -- link
	link=${(e)~fields[1]}
	# -- target
	target=${(e)~fields[2]}
	# -- check if we've already seen this link
	if (( $+linkmap[$link] )); then
		echo "'$link' targets both '$linkmap[$link]' and '$target', aborting"
		exit 1
	fi
	if [ -z "$target" ] || [ -z "$link" ]; then
		echo "Empty link or target provided, skipping"
		continue
	fi
	linkmap[$link]=$target
done < $linksfile

Then later, you can iterate over each key-value pair:

for link target in "${(@kv)linkmap}"; do
	...
done