Dealing with some minified json, switching to iTerm, doing `pbpaste | json_pp | pbcopy` and having a clean output is _so_ nice.
Now, for your Mac example — if that's a specific pipeline you often use, you can write a Service menu entry to do it in place, without switching to a terminal.
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/p...
# This will remove Windows double-spaced empty lines from your copy/paste buffer
alias winlines="sed '/^$/{$!{N;s/\n//;};}'"
# pbw = [P]aste [B]uffer to fix [W]indows line endings
alias pbw="pbpaste | winlines | pbcopy"
Also - if you want `pbpaste` and `pbcopy` on Linux... # imitate MacOS's paste buffer copy/paste:
alias pbcopy='xsel --clipboard --input'
alias pbpaste='xsel --clipboard --output'
This means you can do things like copy an image from the terminal and paste it into a graphical program like a browser or chat client and vice-versa. Also can be very useful in shell scripts for desktop automation.
The workaround on MacOS is to use AppleScript via `osascript` to `set the clipboard to...`.
[0] https://github.com/astrand/xclip
[1] https://github.com/bugaevc/wl-clipboard
alias pbcopy="xclip -selection clipboard"
alias pbpaste="xclip -selection clipboard -o"
It’s so ingrained, I’m more likely than not to just write it out that way even when I know exactly what I’m doing from the onset.
I do this a lot as well, but just paste the minified json directly into VS Code and then OPT+SHIFT+F to format it.
< foo.json jq | pbcopy
alias open="xdg-open"
Instead, they open a file descriptor and pass that.
Tiny difference but there you go.
clip | tr '\n' ' ' | clip
https://github.com/svieira/dotfiles/blob/a3654d6a194e3689978... # Use clipboard in shell pipelines
# clip | xargs echo # uses pbpaste
# ps -A | grep search | clip # uses pbcopy
clip() {
[ -t 0 ] && pbpaste || pbcopy
}
except one time I quickly typed
`cat ~/.ssh/mykey | pbcopy`
And sent it straight away to my coworker on Slack.
I then spent the rest of the day making a new private key and adding my new pubkey to all of the 1000+ servers I had root access to. I mean we had tools to help but it still wasn’t fun.
With great power/convenience comes the potential to do dumb things at lightning speeds!
e.g.
I need to grab some info from textfile.txt to use as arguments to a function.
cat textfile.txt
looks like its comma delimited.
cat textfile.txt | cut -d, -f 2-5
ah, its the third and fourth column i need
cat textfile.txt | cut -d, -f 3-4 | grep '123456'
perfect
cat textfile.txt | cut -d, -f 3-4 | grep 123456 | tr , ' '
myfunc $(cat textfile.txt | cut -d, -f 3-4 | grep 123456 | tr , ' ')
select all in a terminal window with pages of log data and cmd-c copy; find the one phrase you want to find in that data and cmd-e to put it in the find pasteboard; cmd-n new window, type pbg to isolate the log lines.
When you run "cmd < file", the command reads from stdin, which pulls directly from the file. When you do "cat file | cmd", "cat" opens the file, reads from there, and writes to a pipe. Then "cmd" reads from its stdin, which is a pipe.
#!/usr/bin/env python3
import sys
import json
print(json.load(sys.stdin))
And ... ?
In short, I straight up don't care.
The only drawback is that yes it only works most of the time. And when it doesn’t I get infuriated.
Glitches happen without any change to settings or network on my side - it works now, and 5 min later doesn’t.
On the topic, you can also integrate tmux with the native clipboard - I have set copy-pipe to the remote pbcopy, so any selection done in tmux get copied to my local clipboard. I also just found out that tmux also support it natively (https://github.com/tmux/tmux/wiki/Clipboard#the-set-clipboar...).
So I have it enabled so there is a sound when something goes into the clipboard. Even on my mac, I have come to rely on that audio feedback. But it has the added benefit that when I am using my phone in front of my computer and I copy something on my phone, I immediate (and it is impressively fast... maybe a 200ms delay), I hear the chime that something was added to my clipboard on my mac. So it gives you that good feedback that a copy "worked".
You can also shift+cmd+V to see the clipboard history, which is another complimentary tool with universal clipboard because if a paste isn't working as expected you can see if the universal copy never "took" (as you mentioned it is semi-unreliable), or if it just got overridden. You can then use the navigator to paste the older item.
Requiring WiFi makes (so the phone/computer is on a network and can communicate with the other devices), but what's the benefit of Bluetooth? Does it only work when the phone and computer are near each other?
I use most of Apple's "built in" applications like Mail, Notes, Photos, etc. with Firefox (instead of Safari) probably the only exception to that.
lot's of times we sort of know what we are working with, but don't remember the particulars especially
https://developer.apple.com/documentation/uikit/uipasteboard...
pbpaste > tmp; vim tmp; cat tmp | pbcopy; rm tmp;
I also use pbpaste to append various notes to files, but since pbpaste doesnt have a newline at the end I wind up using: echo "$(pbpaste)" >> notes.txt
I've noticed that more and more apps on both macOS and iOS sniff the clipboard contents and randomly clobber it. I usually notice it in apps like Sourcetree, where I'll click something or do a certain action and suddenly I can't paste anymore. I even get a feel for it, like my mind detects the pattern that empties the clipboard so I sense when I can no longer paste, but I can't figure out concrete repeatable steps to make it happen. On iOS it's more random, and I feel like it's probably Facebook doing it, or maybe websites in Safari. I just assume that everything is spying on my clipboard contents now, hoping to log secrets/passwords and PII to sell to scammers.
I have to say, this is one of the more disappointing developments from Apple, that they certainly must know by now about these clipboard shenanigans, but have done nothing to stop them. They need to implement permissions that deny all apps the ability to get/set the clipboard by default, and have an option to ask the user whether so-and-so app can access the clipboard (outside of normal copy/paste), every time with the option to allow always. And all clipboard access attempts should probably get logged somewhere.
> but looking up the arguments and their ordering is annoying
you seem to be arguing for complacency. taking your idea to an extreme, why learn to do _anything_ well?
I still uselessly use cat though, it's such a nice way to build a pipeline.
But I honestly think people who try to optimise away ‘cat’ are optimising the wrong thing. If one extra fork() is that detrimental then don’t use a shell scripting language.
For a lot of people, “useless” ‘cat’ enables them to write a pipeline in the order that their brain farts out the requirements for the pipeline. So they’ve optimised for human productivity. And given the human brain is slower than a few extra fork()s, I think optimising for one’s brain makes more sense here.
I recognize that your pbg alias works for pretty much any text you could copy, but I wanted to mention, in case you're looking at log files with plain old less, there's the & limiter, which limits the current view to only lines matching a regular expression (or, if you type ^R during a & prompt, for a text match).
If you type ^N or ! during a & prompt it will limit the view to those lines that do not match the expression.
These view limits stack, so you can "&WARN<enter>" to see all lines that have WARN in them, and then maybe you want to see just a certain PID so "&12345<enter>" and you'll only see lines with both WARN and 12345, but then that one module is printing out a bunch of messages you think are safe to ignore so you do "&!modulename<enter>" and it filters out log lines that match modulename. Very handy and less is everywhere.
For instance, in Shortcuts, I see that there's a "Pin Notes" action for Notes.app, but I don't see anything for pinning notes when I open Notes.app with "File -> Open Dictionary..." in Script Editor.
(In this case it's likely that Notes.app has the a11y bits necessary to run that action from Hammerspoon, but it would probably be easier to go through Shortcuts.)
pbpaste | vipe | pbcopy
Where vipe is a util for inserting your editor (vim) in the middle of a pipe. From: https://joeyh.name/code/moreutils/Another sometimes-important difference is that if there are multiple input files, `somecommand file1 file2 file3` can tell what data is coming from which file; with `cat file1 file2 file3 | somecommand` they're all mashed together, and the program has no idea what's coming from where.
In general, though, I think it's mostly a matter of people's expertise level in using the shell. If you're a beginner, it makes sense to learn one very general way to do things (`cat |`), and use it everywhere. But as you gain expertise, you learn other ways of doing it, and will choose the best method for each specific situation. While `cat |` is usually an ok method to read from a file, it's almost never the best method, so expert shell users will almost never use it.
[1] http://redsymbol.net/articles/unofficial-bash-strict-mode/
Many of my programs and scripts start output with the line: # cmd arg1 arg2 arg3 ...
and simply echo back lines that start with '#'. That way, I have an internal record of the program that was run and the data file that was read (as well as previous parts of the analysis chain).
And, 'R' ignores lines starting with '#', so the record is there, but does not affect later analyses.
pbfilter() {
if [ $# -gt 0 ]; then
pbpaste | "$@" | pbcopy
else
pbpaste | pbcopy
fi
}
Then you can use something like `pbfilter json_pp` or `pbfilter base64 -d` or `pbfilter sed 's/this/that/'` or whatever.This version also can also act as a plain-text-only filter. If you just use `pbfilter` with no argument, it'll remove any formatting from the text in the pasteboard, leaving just straight plain text.
It does have a some limitations, though: you can't use it with an alias, or pipeline, or anything complex like that. The filter command must be a single regular command (or function) and its arguments.
Being able to populate or read from the system clipboard (or secondary clipboard!), or to feed it, including by reading from or writing to pipes is wonderful.
I have found a lot of utility with cross-device copy/paste. I know it requires the somewhat mysterious phantom Bluetooth/Wi-Fi connectivity that AirPlay/Airdrop use, so if I have disabled Bluetooth on my device, for example, it will no longer work. I could see where it might not be fully reliable enough to count on, I have experienced inexplicable failures, not often but enough to understand that it might not be some folks’ default preference. As part of the “handoff” function, it can be disabled in Settings at least.
alias clip='pbcopy <'
Are you sure? https://unix.stackexchange.com/questions/208615/is-cat-a-she... disagrees and neither https://manpages.ubuntu.com/manpages/jammy/man7/bash-builtin... nor https://zsh.sourceforge.io/Doc/Release/Shell-Builtin-Command... mention it
> It’s just not the same syntax (ie ‘< filename’).
Reading from a file isn’t a hard problem. Having a good UX for doing that is where most shells fall apart. And that’s basically what ‘cat’ offers here: an improved UX.
Having ‘cat’ as a shell builtin wouldn’t really solve the complaints raised by “useless use of” anyway because you’d still be piping (and in some cases, fork()ing too). You couldnt really use ‘cat’ as syntactic sugar for ‘<‘ because things start to get really weird if you want to pass flags to ‘cat’ or even redirect the output to something other than a pipe. And given ‘cat’ is POSIX (https://en.m.wikipedia.org/wiki/List_of_Unix_commands#/media...) the current behaviour of shells is, in my opinion, correct. This is why my own shell has a differently named builtin that approximately serves the purpose of ‘cat’ but for instances when you need the command built into the shell and it can’t just be passing a file handle to the next command (in my case, because i wanted to pass metadata out-of-band as well as the file contents)
I download and save it as 'ytdl' for convenience, but I use it all the time on twitter too.
Even the Wikipedia page on cat has a section about that, titled eponymously.
copy_file_range allows a user land program to copy data between two files without doing any user space work. Instead of reading data into a buffer and writing it back out to the destination, the kernel will somehow manage to move the data for you.
I think this will prevent any extra copies from occurring in situations where it can be used.
https://man.archlinux.org/man/copy_file_range.2
https://git.savannah.gnu.org/cgit/coreutils.git/tree/src/cat...
https://georgegarside.com/blog/macos/fix-apple-watch-auto-un...
In their iOS app, there’s an entry in Settings -> Security -> Allow Universal Clipboard which lets you opt-in to passwords through the clipboard. I suspect there’s something similar on macOS.
But do you know why it doesn't seem to work with the `pbfilter` function?
If I do directly `pbpaste | vipe | pbcopy`, then it opens vim and the clipboard text is pasted there. But if I run `pbfilter | vipe`, then vim opens with a blank buffer.
function pbfilter() {
if [ $# -gt 0 ]; then
pbpaste | "$@" | pbcopy
else
pbpaste | pbcopy
fi
}
It seems that the number of args is 0 for some reason pbcopy | python -m json.tool | pbpaste
It has a load options: $ python -m json.tool --help
usage: python -m json.tool [-h] [--sort-keys] [--no-ensure-ascii] [--json-lines] [--indent INDENT | --tab | --no-indent | --compact] [infile] [outfile]
A simple command line interface for json module to validate and pretty-print JSON objects.
positional arguments:
infile a JSON file to be validated or pretty-printed
outfile write the output of infile to outfile
options:
-h, --help show this help message and exit
--sort-keys sort the output of dictionaries alphabetically by key
--no-ensure-ascii disable escaping of non-ASCII characters
--json-lines parse input using the JSON Lines format. Use with --no-indent or --compact to produce valid JSON Lines output.
--indent INDENT separate items with newlines and use this number of spaces for indentation
--tab separate items with newlines and use tabs for indentation
--no-indent separate items with spaces rather than newlines
--compact suppress all whitespace separation (most compact)
`if read -r -t0; then` # returns true if there is data but times out instantly so it doesn't consume any
Is `[ -t 0 ]` more idiomatic? Apparently it fails on this case: function < file
`read -r -t0` is Bash-only though and not POSIX, but it will work regardless of what type of data is on stdin
But thank you for the share, it is interesting!
[1]: https://github.com/roy2220/osc52pty/blob/master/oscexecutor....
Turning off Bluetooth or wifi may be one of the more common reasons it doesn’t work. Some people never do that, but others do.
You can wrap your ssh session with it and you’re done.
It’s very elegant and multiple orders of magnitude less complex than something like tmux.
:w !pbcopy
or visual selection, and then :w !pbcopy