[HN Gopher] Moreutils: A collection of Unix tools that nobody th... ___________________________________________________________________ Moreutils: A collection of Unix tools that nobody thought to write long ago Author : escot Score : 279 points Date : 2022-04-15 18:16 UTC (4 hours ago) (HTM) web link (joeyh.name) (TXT) w3m dump (joeyh.name) | sundarurfriend wrote: | The "What's included" section direly needs either clearer/longer | descriptions, or at least links to the tools' own pages (if they | have them) where their use case and usage is explained. I've | understood a lot more about (some of) the tools from the comments | here than from the page - and I'd likely have skipped over these | very useful tools if not for these comments! | sundarurfriend wrote: | Ok, longer descriptions from the tools' man pages: | | --- | | chronic runs a command, and arranges for its standard out and | standard error to only be displayed if the command fails (exits | nonzero or crashes). If the command succeeds, any extraneous | output will be hidden. | | A common use for chronic is for running a cron job. Rather than | trying to keep the command quiet, and having to deal with mails | containing accidental output when it succeeds, and not verbose | enough output when it fails, you can just run it verbosely | always, and use chronic to hide the successful output. | | --- | | combine combines the lines in two files. Depending on the | boolean operation specified, the contents will be combined in | different ways: | | and Outputs lines that are in file1 if they are also present in | file2. | | not Outputs lines that are in file1 but not in file2. | | or Outputs lines that are in file1 or file2. | | xor Outputs lines that are in either file1 or file2, but not in | both files. | | The input files need not be sorted | | --- | | ifdata can be used to check for the existence of a network | interface, or to get information about the interface, such as | its IP address. Unlike ifconfig or ip, ifdata has simple to | parse output that is designed to be easily used by a shell | script. | | --- | | lckdo: Now that util-linux contains a similar command named | flock, lckdo is deprecated, and will be removed from some | future version of moreutils. | | --- | | mispipe: mispipe pipes two commands together like the shell | does, but unlike piping in the shell, which returns the exit | status of the last command; when using mispipe, the exit status | of the first command is returned. | | Note that some shells, notably bash, do offer a pipefail | option, however, that option does not behave the same since it | makes a failure of any command in the pipeline be returned, not | just the exit status of the first. | | --- | | pee: [my own description: `pee cmd1 cmd2 cmd3` takes the data | from the standard input, sends copies of it to the commands | cmd1, cmd2, and cmd3 (as their stdin), aggregates their outputs | and provides that at the standard output.] | | --- | | sponge, ts and vipe have been described in other comments in | this thread. (And I've also skipped some easier-to-understand | ones like errno and isutf8 for the sake of length.) | | --- | | zrun: Prefixing a shell command with "zrun" causes any | compressed files that are arguments of the command to be | transparently uncompressed to temp files (not pipes) and the | uncompressed files fed to the command. | | The following compression types are supported: gz bz2 Z xz lzma | lzo | | [One super cool thing the man page mentions is that if you | create a link named z<programname> eg. zsed, with zrun as the | link target, then when you run `zsed XYZ`, zrun will read its | own program name, and execute 'zrun sed XYZ' automatically.] | | --- | caymanjim wrote: | They come with good manpages if you install them. I don't | disagree that a little more detail on the linked web page might | help people decide whether or not to install, but in keeping | with how these are well-behaved oldschool-style Unix commands, | they also come with man pages, which is more than I can say for | most command line tools people make today (the ones that assume | you have Unicode glyphs and color terminals [and don't check if | they're being piped or offer --no-color] and don't accept | -h/--help and countless other things that kids these days have | eschewed). | caymanjim wrote: | I was prepared to mock this before I even clicked, but I have to | say this looks like a nice set of tools that follow the ancient | Unix philosophy of "do one thing, play nice in a pipeline, stfu | if you have nothing useful to say". Bookmarking this to peer at | until I internalize the apps. There's even an Ubuntu package for | them. | | I don't think it's a good idea to rely on any of these being | present. If you write a shell script to share and expect them to | be there, you aren't being friendly to others, but for | interactive command line use, I'm happy to adopt new tools. | nonrandomstring wrote: | > Bookmarking this to peer at until I internalize the apps. | There's even an Ubuntu package for them. | | Ditto. But I will probably forget they exist and go do the same | old silly kludges with subshells and redirections. May I ask if | anyone has a technique for introducing new CL tools into their | everyday workflow? | | It helps if things have good man, apropos and help responses, | but the problem is not _how_ new tools function, rather | remembering that they exist at all. | | Sometimes I think I want a kind of terminal "clippy" that says: | | "Looks like you're trying to match using regular expressions, | would you like me to fzf that for you?" | | Then again, maybe not. | bcbrown wrote: | > May I ask if anyone has a technique for introducing new CL | tools into their everyday workflow? | | Pick one tool a year. Write it on a sticky note on your | monitor. Every time you're doing something on the command | line, ask yourself "would $TOOL be useful here?". | | You're not going to have high throughput on learning new | tools this way, but it'll be pretty effective for the tools | you do learn. | chrisshroba wrote: | My two cents on this is that if you do something enough that | one of these tools is a good tool for it, it'll quickly | become a habit to use the tool. And if there's a rare case | where one of these tools would have been useful but you | forgot it existed, you're probably not wasting _too_ much | time using a hackier solution. | | That being said, I've been meaning to add a Linux and Mac | install.sh script to my dotfiles repo for installing all my | CLI tools, and that could probably serve as a good reminder | of all the tools you've come across over the years that might | provide some value. | _dain_ wrote: | >I don't think it's a good idea to rely on any of these being | present. If you write a shell script to share and expect them | to be there, you aren't being friendly to others, but for | interactive command line use, I'm happy to adopt new tools. | | Isn't that a shame though? Where does it say in the UNIX | philosophy that the canon should be closed? | Delk wrote: | It's not that different than refraining from using non-POSIX | syntax in shell scripts that are meant to be independent of a | specific flavour of unix, or sticking with standard C rather | than making assumptions that are only valid in one compiler. | | There are shades of grey, of course. Bash is probably | ubiquitous enough that it may not be a big issue if a script | that's meant to be universal depends on it, as long as the | script explicitly specifies bash in the shebang. Sometimes | some particular functionality is not technically part of a | standard but is widely enough supported in practice. | Sometimes the standards (either formal or de facto) are | expanded to include new functionality, and that's of course | totally fine, but it's not likely to be a very quick process | because there are almost certainly going to be differing | opinions on what should be part of the core and what | shouldn't. | | Either way, sometimes you want to write for the lowest common | denominator, and moreutils certainly aren't common enough | that they could be considered part of that. | caymanjim wrote: | I think it's fine if you're on a dev team that decides to | include these tools in its shared toolkit, but none of these | rise to the level that I think warrants them being a | dependency for a broadly-distributed shell script. There are | slightly-less-terse alternatives for most of the | functionality that only rely on core utilities. I don't think | it's being a good citizen to say "go install moreutils and | its dozen components because I wanted to use sponge instead | of >output.txt". | pjungwir wrote: | These are necessarily bash functions, not executables, but here | are two tools I'm proud of, which seem similar in spirit to vidir | & vipe: # Launch $EDITOR to let you edit your | env vars. function viset() { if [ -z "$1" | ]; then echo "USAGE: viset THE_ENV_VAR" | exit 1 else declare -n ref=$1 | f=$(mktemp) echo ${!1} > $f $EDITOR $f | ref=`cat $f` export $1 fi } | # Like viset, but breaks up the var on : first, # then | puts it back together after you're done editing. # | Defaults to editing PATH. # # TODO: Accept a | -d/--delimiter option to use something besides :. | function vipath() { varname="${1:-PATH}" | declare -n ref=$varname f=$(mktemp) echo | ${!varname} | tr : "\n" > $f $EDITOR $f | ref=`tr "\n" : < $f` export $varname } | | Mostly I use vipath because I'm too lazy to figure out why tmux | makes rvm so angry. . . . | | I guess a cool addition to viset would be to accept more than one | envvar, and show them on multiple lines. Maybe even let you edit | your entire env if you give it zero args. Having autocomplete-on- | tab for viset would be cool too. Maybe even let it interpret | globs so you can say `viset AWS*`. | | Btw I notice I'm not checking for an empty $EDITOR. That seems | like it could be a problem somewhere. | I_complete_me wrote: | I only install moreutils for vidir which is simply brilliant IMO | teddyh wrote: | I prefer Emacs dired, where pressing C-x C-q starts editing the | opened directory (including any inserted subdirectories). | [deleted] | VTimofeenko wrote: | One alias I always do is "vidir" -> "vidir --verbose" so that | it would tell me what it's doing | zzo38computer wrote: | I have this installed and have used some of these sometimes; it | is good. (I do not use all of them, though) | WalterBright wrote: | > errno: look up errno names and descriptions | | I like this. Reminds me of a couple very useful things I've done: | | 1. Add a -man switch to command line programs. This causes a | browser to be opened on the web page for the program. For | example: dmd -man | | opens https://dlang.org/dmd-windows.html in your default browser. | | 2. Fix my text editor to recognize URLs, and when clicking on the | URL, open a browser on it. This silly little thing is amazingly | useful. I used to keep bookmarks in an html file which I would | bring up in a browser and then click on the bookmarks. It's so | much easier to just put them in a plain text file as plain text. | I also use it for source code, for example the header for code | files starts with: /* * Takes a token | stream from the lexer, and parses it into an abstract syntax | tree. * * Specification: $(LINK2 | https://dlang.org/spec/grammar.html, D Grammar) * | * Copyright: Copyright (C) 1999-2020 by The D Language | Foundation, All Rights Reserved * Authors: $(LINK2 | http://www.digitalmars.com, Walter Bright) * License: | $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) | * Source: $(LINK2 | https://github.com/dlang/dmd/blob/master/src/dmd/parse.d, | _parse.d) * Documentation: | https://dlang.org/phobos/dmd_parse.html * Coverage: | https://codecov.io/gh/dlang/dmd/src/master/src/dmd/parse.d | */ | | and I'll also use URLs in the source code to reference the spec | on what the code is implementing, and to refer to closed bug | reports that the code fixes. | | Very, very handy! | HellsMaddy wrote: | I find sponge really useful. Have you ever wanted to process a | file through a pipeline and write the output back to the file? If | you do it the naive way, it won't work, and you'll end up losing | the contents of your file: awk '{do_stuff()}' | myfile.txt | sort -u | column --table > myfile.txt | | The shell will truncate myfile.txt before awk (or whatever | command) has a chance to read it. So you can use sponge instead, | which waits until it reads EOF to truncate/write the file. | awk '{do_stuff()}' myfile.txt | sort -u | column --table | sponge | myfile.txt | mzs wrote: | If you're using awk anyway: awk | 'BEGIN{system("rm myfile.txt")}{do_stuff()}' <myfile.txt | sort | -u | column --table > myfile.txt | | In general though: <foo { rm -f foo && wc >foo | } | jwilk wrote: | Your awk pipeline is racy. | indigodaddy wrote: | Never heard of sponge. Isn't it just the same as tee ? | halostatue wrote: | It's part of the moreutils collection and is better | considered a buffered redirect than anything similar to | `tee`. | indigodaddy wrote: | Ah yes I glanced too quickly over the surface here. It does | look more like redirection. Will have to look at it more. | Appreciate your helpful response vs the downvoters and the | one unhelpful/snarky response. | AshamedCaptain wrote: | The point is not to truncate the file immediately when it is | open for output, and before the input side has had time to | slurp it. | binwiederhier wrote: | I urge you to actually read the link before commenting. | sponge is the front and center example of the link you are | commenting on. | indigodaddy wrote: | The downvoting here is the equivalent of getting shamed for | "asking a stupid question at work." | | Yes I should have done a bit more homework but shaming for | asking a clarifying question is unreasonable. Those of you | who have the downvote trigger-finger can and should do | better. | HellsMaddy wrote: | I agree with you, the downvotes are unnecessary, it was | actually a good question. | | tee actually does sorta work for this sometimes, but it's | not guaranteed to wait until EOF. For example I tested with | a 10 line file where I ran `sort -u file.txt | tee | file.txt` and it worked fine. But I then tried a large json | file `jq . large.json | tee large.json` and the file was | truncated before jq finished reading it. | thanatos519 wrote: | 'sort -o file' does the same thing but I like the generic | 'sponge'. Not sure why it's a binary, since it's basically this | shell fragment (if you don't bother checking for errors etc): | | (cat > $OUT.tmp; mv -f $OUT.tmp $OUT) | | Hmmm ... "When possible, sponge creates or updates the output | file atomically by renaming a temp file into place. (This | cannot be done if TMPDIR is not in the same filesystem.)" | | My shell fragment already beats sponge on this feature! | caymanjim wrote: | I can see how this is handy, but it's also dangerous and likely | to bite you in the ass more than not. I think sponge is great, | but I think your example is dangerous. If you make a mistake | along the way, unless it's a fatal error, you're going to lose | your source data. Typo a grep and you're screwed. | justsomehnguy wrote: | Agree. | | Sure there could be some situations where it could be handy, | like in some auomated scenarios, but most of the time it is | not a big deal to write foo data1 data2 | bar data2 | HellsMaddy wrote: | Right. You should always test the command first. If the data | is critical, use a temporary file instead. I usually use this | in scripts so I don't have to deal with cleanup. | sedatk wrote: | > If the data is critical, use a temporary file instead | | Use a temporary file always. Sponge process may be | interrupted, and you end up with a half-complete | /etc/passwd in return. | rcoveson wrote: | Couldn't `mv` or `cp` from the temp file to `/etc/passwd` | be interrupted as well? I think the only way to do it | atomically is a temporary file on the same filesystem as | `/etc`, followed by a rename. On most systems `/tmp` will | be a different filesystem from `/etc`. | AdamJacobMuller wrote: | mv can't, or, more correctly the rename system call can | not. | | rename is an atomic operation from any modern | filesystem's perspective, you're not writing new data, | you're simply changing the name of the existing file, it | either succeeds or fails. | | Keep in mind that if you're doing this, mv (the command | line tool) as opposed to the `rename` system call, falls | back to copying if the source and destination files are | on different filesystems since you can not really mv a | file across filesystems! | | In order to have truly atomic writes you need to: | | open a new file on the same filesystem as your | destination file | | write contents | | call fsync | | call rename | | call sync (if you care about the file rename itself never | being reverted). | | This is some very naive golang code (from when I barely | knew golang) for doing this which has been running in | production since I wrote it without a single issue: https | ://github.com/AdamJacobMuller/atomicxt/blob/master/file.. | . | JJMcJ wrote: | Not clear on need for fsync and sync. | | Are those for networked like NTFS or just as security | against crashes. | | Logically on a single system there would be no effect | assuming error free filesystem operation. Unless I'm | missing something. | antihero wrote: | Why not write it to a different file | Quekid5 wrote: | This is why I usually just use a temporary directory and do | a quick git init . git add . | git commit -m "wip" | | ... and proceed from there. So many ways to screw up ad hoc | data processing using shell and the above can be a life | saver. (Along with committing along the way, ofc.) | | EDIT: Doesn't work if you have huuuuge files, obviously... | but you should perhaps be using different tools for that | anyway. | chungy wrote: | You might like to try using src, a simple single-file VC: | http://www.catb.org/esr/src/ | uuyi wrote: | Been there done that. Good advice. | | In my case I could recreate the original file but it took 90 | minutes to scrape the remote API to do it again... | dan-robertson wrote: | I usually used tac | tac for a stupid way of pausing in a | pipeline. Though it doesn't work in this case. A typical use is | if you want to watch the output of something slow-to-run | changing but watch doesn't work for some reason, eg: | while : ; do ( tput reset run-slow-command ) | | tac | tac done | alerighi wrote: | It would also be useful in cases when the file must be written | with root privileges (but the shell is run as a normal user) | | Now you have to use `tee` for that, that is fine but if you | don't want to echo the file back to the terminal you have to do | command | sudo tee file > /dev/null | | with this you can simply do command | sudo | sponge file | leni536 wrote: | Can't you just use `cat`? | jaden wrote: | I thought the same thing. What's wrong with this approach? | cat myfile.txt | awk '{do_stuff()}' | sort -u | column | --table > new-myfile.txt | HellsMaddy wrote: | cat is doing nothing useful here. Your command is | equivalent to awk '{do_stuff()}' | myfile.txt | sort -u | column --table > new-myfile.txt | | The only thing you've changed is that you're sending the | output to a new file. That's fine, but it's what sponge | is avoiding. | ben0x539 wrote: | You cannot use `sudo cat` to open a file with root | privileges, because `sudo cat > foo` means "open file foo | with your current privileges, then run `sudo cat` passing | the file to it", and the whole root thing only happens | after you already tried and failed to open the file. | | I seem to get this wrong roughly once a week. | gorgoiler wrote: | ... | sudo tee foo | readme wrote: | sudo sh -c "cat > file" | HellsMaddy wrote: | Cat won't write the file. If you mean `command | sudo cat > | file.txt`, that won't work because the redirection is still | happening in the non-root shell. You could do `command | | sudo sh -c "cat > file.txt"` but that's rather verbose. | justinsaccount wrote: | protip: don't run this awk '{do_stuff()}' | myfile.txt | sort -u | column --table | sponge > myfile.txt | jamespwilliams wrote: | Are there any legitimate reasons to have a particular file both | as an input to a pipe and as an output? I wonder whether a | shell could automatically "sponge" the pipe's output if it | detected that happening. | mjochim wrote: | sed --in-place has one file as both input and output. It's | not really different from any pipe of commands where the | input and output files are the same. But sed also makes a | copy of the file before overwriting it - per default. | teawrecks wrote: | Yeah, it seems like the kind of command that you only need | because of a quirk in how the underlying system happens to | work. Not something that should pollute the logic of the | command, imo. I would expect a copy-on-write filesystem to be | able to do this automatically for free. | caymanjim wrote: | Do people really use copy-on-write filesystems though? I | mean it'd be great if that were a default, but I rarely | encounter them, and when I do, it's only because someone | intentionally set it up that way. In 30+ years of using | Unix systems, I can't even definitively recall one of them | having a copy-on-write filesystem in place. Which is insane | considering I used VAX/VMS systems before that and it was | standard there. | r3trohack3r wrote: | FreeBSD uses ZFS by default, which is copy on write post- | snapshot. | mjochim wrote: | Huh? Btrfs is copy on write and it's definitely being | used. | paulmd wrote: | > I would expect a copy-on-write filesystem to be able to | do this automatically for free. | | this is an artifact of how handles work (in relation to | concurrency), not the filesystem. | | copy-on-write still guarantees a consistent view of the | data, so if you write on one handle you're going to clobber | the data on the other, _because that 's what's in the | file_. | | what you really want is an operator which says "I want this | handle to point to the original snapshot of this data even | if it's changed in the meantime", which a CoW filesystem | _could_ do, but you 'd need some additional semantics here | (different access-mode flag?) which isn't trivially granted | just by using a CoW filesystem underneath. | Arnavion wrote: | The shell can't detect that unless the file is also used as | input via `<`. So it couldn't do that in HellsMaddy's | example, since the filename is given as an arg to awk instead | of being connected to its stdin. | RulerOf wrote: | >I find sponge really useful. | | When I found `sponge`, I couldn't help but wonder where it had | been all of my life. It's nice to be able to modify an in-place | file with something other than `sed`. | JoshTriplett wrote: | I use a few of these regularly: | | ts timestamps each line of the input, which I've found convenient | for ad-hoc first-pass profiling in combination with verbose print | statements in code: the timestamps make it easy to see where long | delays occur. | | errno is a _great_ reference tool, to look up error numbers by | name or error names by number. I use this for two purposes. | First, for debugging again, when you get an errno numerically and | want to know which one it was. And second, to search for the | right errno code to return, in the list shown by errno -l. | | And finally, vipe is convenient for quick one-off pipelines, | where you know you need to tweak the input at one point in the | pipeline but you know the nature of the tweak would take less | time to do in an editor than to write the appropriate tool | invocation to do it. | ducktective wrote: | I actually installed moreutils just for errno, but I got | disappointed. Here it the whole `errno -l` : http://ix.io/3VeV | | Like, none of the everyday tools I use produce exit codes which | correspond to these explanations. | | For my scripts, I just return 1 for generic erros and 2 for bad | usage. I wished I could be more specific in that and adhered to | _some standard_. | JoshTriplett wrote: | errno codes aren't used in the exit codes of command-line | tools; they're used in programmatic APIs like syscalls and | libc functions. | | There's no standard for process exit codes, other than "zero | for success, non-zero for error". | zzo38computer wrote: | Some programs do follow a specification (sysexits.h) where | numbers 64 and higher are used for common uses, such as | usage error, software error, file format error, etc. | ithkuil wrote: | Aldo when the oomkiller process kills another process it | causes it to exit with a well known exit code: 137 | saagarjha wrote: | That's just 128+SIGKILL (9). | teddyh wrote: | That's not an exit code; that is a fake exit code which | your shell made up, since your shell has no other way to | tell you that a process did not exit at all, but was | killed by a signal (9, i.e. SIGKILL). This is, again, not | an actual exit code, since the process did not actually | exit. | | See here for why you can't use an exit status of | 128+signal to fake a "killed by signal" state, either: | | https://www.cons.org/cracauer/sigint.html | teddyh wrote: | That is not entirely true. There _is_ sysexits.h, which | tried to standardize some exit codes (originally meant for | mail filters). It is used by, for instance, argp_parse(). | | https://sourceware.org/git/?p=glibc.git;a=blob;f=misc/sysex | i... | drewg123 wrote: | Its a shame errno is even needed, and is one of my pet peeves | about linux. | | On linux, errno.h is fragmented across several places because | errnos are _different_ on different architectures. I think this | started because when Linus did the initial alpha port, he | bootstrapped Linux using a DEC OSF /1 userland, which meant | that he had to use the DEC OSF/1 BSD-derived values of errno | rather than the native linux ones so that they would run | properly. I'm not sure why this wasn't cleaned up before it | made it into the linux API on alpha. | | At least on FreeBSD, determining what errno means what is just | a grep in /usr/include/sys/errno.h. And it uses different | errnos for different ABIs (eg, linux binaries get their normal | errnos, not the FreeBSD ones). | tedunangst wrote: | Freebsd doesn't have man errno?? | hgomersall wrote: | Are they written in rust? If not, it's just more programmes | someone is going you have to rewrite at some point _sigh_. | jedberg wrote: | My favorite missing tool of all time is `ack` [0]. It's grep if | grep were made now. I use it all the time, and it's the first | thing I install on a new system. | | It has a basic understanding of common text file structures and | also directories, which makes it super powerful. | | [0] https://beyondgrep.com | renewiltord wrote: | ripgrep is a modern written-in-Rust[0] equivalent that I really | like. | | 0: I like this because it's much easier to edit IMHO | outworlder wrote: | What about the Silver Searcher? It's even faster than ack | | https://github.com/ggreer/the_silver_searcher | makeworld wrote: | What about ripgrep? It's even faster than the Silver Searcher | | https://github.com/BurntSushi/ripgrep | jedberg wrote: | Had never heard of it before, but I'll definitely check it | out now. Thanks! | usr1106 wrote: | I have searched ts for a long time. Used it many years ago but | forgot the exact name of the tool and package. No search machine | could find it or I just entered to wrong search words. | topher200 wrote: | The one I use the most is `vipe`. | | > vipe: insert a text editor into a pipe | | It's useful when you want to edit some input text before passing | it to a different function. For example, if I want to delete many | of my git branches (but not all my git branches): | $ git branch | vipe | xargs git branch -D | | `vipe` will let me remove some of the branch names from the list, | before they get passed to the delete command. | LukeShu wrote: | I vaguely recall in ~2010 coming across a Plan 9 manpage(?) | that seemed to imply that Emacs could work that way in a pipe | (in reference to complex/bloated tools on non-Plan 9 systems), | but that wasn't true of any version of Emacs I'd ever used. | e40 wrote: | Yep, set EDITOR to emacsclient and vipe will use emacs. | unkulunkulu wrote: | I mostly rely on fzf for stuff like this nowadays. You can | replace vipe with fzf --multi for example and get non-inverted | behavior with fuzzy search. | | More to it, not in a pipe (because of poor ^C behavior), but | using a hokey in zsh to bring up git branch | fzf, select any | number of branches I need and put them on command line, this is | extremely composable. | bombcar wrote: | This is useful - I usually either use an intermediate file or a | bunch of grep -v | orblivion wrote: | And what if you decide mid-vipe "oh crap I don't want to do | this anymore"? In the case of branches to delete you could just | delete every line. In other cases maybe not? | goodside wrote: | To be fair, that scenario would be just as bad or worse | without vipe. | | Also, you can construct your pipeline so that a blank file | (or some sentinel value) returned from vipe means "abort". A | good example of this is when git opens your editor for | interactive merging -- deleting all lines cancels the whole | thing. | orblivion wrote: | Yeah you could just as well say "oh crap I didn't mean to | do that" after finishing a non-interactive command. | However, at least knowing my own lazy tendencies, I could | imagine feeling comfortable hitting <enter> on this command | without a final careful review, because part of me thinks | that I can still back out, since the interactive part isn't | finished yet. | | But maybe not. I haven't tried it yet (and it does seem | really useful). | saagarjha wrote: | Send a SIGTERM to the editor, maybe? | Beltalowda wrote: | And there's always the power button on your computer :-) | orblivion wrote: | Kind of ugly, but yeah, that's what I'd imagine doing. | throwaway09223 wrote: | It will depend on the commands in question. The entire unix | pipeline is instantiated in parallel, so the commands | following vipe will already be running and waiting on stdin. | | You could kill them before exiting the editor, if that's what | you want. Or you could do something else. | | The other commands in the pipeline are run by the parent | shell, not vipe, so handling this would not be vipe specific. | delusional wrote: | Depends on your editor i suppose, but vipe checks the exit | code of it [1]. In vim you can exit with an error using :cq | | [1]: https://github.com/pgdr/moreutils/blob/f4a811d0a1fafb3d7 | b0e7... | foresto wrote: | Exiting vim with :cq is also handy for backing out of git | commits. | _joel wrote: | Working with *nix for over 25 years and I've only just heard of | sponge. | PaulDavisThe1st wrote: | The need for ifdata(1) has become even more acute with the | essential replacement of ifconfig(1) by ip(1), an even more | inscrutable memory challange. However, it would be even nicer if | its default action when not given an interface name was do | <whatever> for all discovered interfaces. | teddyh wrote: | Do not "ip -brief address show" and "ip -brief link show" serve | as suitable replacements for most common uses of ifdata(1)? The | ip(8) command even supports JSON output using "-json" instead | of "-brief". | zwayhowder wrote: | TIL. Thanks. | | One does have to wonder though, why isn't -brief the default | and the current default set to -verbose or -long. I look at | -brief on either command and it has all the information I am | ever looking for. | Filligree wrote: | Yes, I suppose, but I can never remember those flags. | wang_li wrote: | Amazing how many new things come about because people don't | know or don't remember how to use the existing things. | teddyh wrote: | ifdata is not meant for interactive use. | hedora wrote: | Well, they're strictly worse for interactive use than | ifconfig, from what I can tell from your comment. | teddyh wrote: | We were discussing ifdata, not ifconfig. From the | documentation, ifdata is explicitly meant for use in | scripts. And in scripts, using "ip -brief" or "ip -json ... | | jq ..." may well be suitable replacements for ifdata. | PaulDavisThe1st wrote: | Sure, they do. | | In fact, I take it back. ifdata(1) is not in any way a | replacement for ifconfig(1) for most things. The problem is | that just running ifconfig with no arguments showed you | everything, which was generally perfect for interactive use. | Now to get _any_ information from ip(1) you have to remember | an argument name. If you do this a lot, it 's almost | certainly fine. If you do it occasionally, it's horrible. | ChrisGranger wrote: | It's been a _very_ long time since this happened, but in my early | days of using Linux, I experienced naming collisions with both | sponge and parallel, and at the time I didn 't know how to | resolve them. I don't remember which other sponge there was, but | I imagine most Linux users are familiar with GNU parallel at this | point. | JulianWasTaken wrote: | moreutils indeed has some great utils, but a minor annoyance it | causes is still shipping a `parallel` tool which is relatively | useless, but causes confusion for new users or conflict (for | package managers) with the way way way more indispensable GNU | parallel. | yesenadam wrote: | When I installed moreutils v0.67 with macports just now it | said: moreutils has the following notes: | The binary parallel is no longer in this port; please install | the port parallel instead. | | i.e. GNU parallel | omoikane wrote: | `parallel` seems redundant because it appears that `xargs -P` | can accomplish the same effect, except the "-l maxload" option. | Davertron wrote: | So just today I was wondering if there was a cli tool (or maybe a | clever use of existing tools...) that could watch the output of | one command for a certain string, parse bits of that out, and | then execute another command with that parsed bit as input. For | example, I have a command I run that spits out a log line with a | url on it, I need to usually manually copy out that url and then | paste it as an arg to my other command. There are other times | when I simply want to wait for something to start up (you'll | usually get a line like "Dev server started on port 8080") and | then execute another command. | | I know that I could obviously grep the output of the first | command, and then use sed or awk to manipulate the line I want to | get just the url, but I'm not sure about the best way to go about | the rest. In addition, I usually want to see all the output of | the first command (in this case, it's not done executing, it | continues to run after printing out the url), so maybe there's a | way to do that with tee? But I usually ALSO don't want to | intermix 2 commands in the same shell, i.e. I don't want to just | have a big series of pipes, Ideally I could run the 2 commands | separately in their own terminals but the 2nd command that needs | the url would effectively block until it received the url output | from the first command. I have a feeling maybe you could do this | with named pipes or something but that's pretty far out of my | league...would love to hear if this is something other folks have | done or have a need for. | ufo wrote: | A named pipe sounds like a good way to fulfill your requirement | of having the command runs on separate shells.. In the first | terminal, shove the output of commend A into the named pipe. In | the second terminal, have a loop that reads from the named pipe | line by line and invokes command B with the appropriate | arguments. | | You can create a named pipe using "mkfifo", which creates a | pipe "file" with the specified name. Then, you can tell your | programs to read and write to the pipe the same way you'd tell | them to read and write from a normal file. You can use "<" and | ">" to redirect stdout/stderr, or you can pass the file name if | it's a program that expects a file name. | nix0n wrote: | There's a tool for this type of thing called Expect[0], written | in TCL. | | [0] https://core.tcl-lang.org/expect/index | abbeyj wrote: | In one terminal, run: $ mkfifo myfifo $ | while true; do sed -rune 's/^Dev server started on port | (.*)/\1/p' myfifo | xargs -n1 -I{} echo "Execute other command | here with argument {}"; done | | In the other terminal, run your server and tee the output to | the fifo you just created: $ start_server | tee | myfifo | sillysaurusx wrote: | Thanks for this! | teddyh wrote: | I'd solve your exact problem like this: | | 1. Run one command with output to a file, possibly in the | background. Since you want to watch the output, run "tail | --follow=name filename.log". | | 2. In a second terminal, run a second tail --follow on the same | log file but pipe the output to a command sequence to find and | extract the URL, and then pipe _that_ into a shell while loop; | something like "while read -r url; do do-thing-with "$url"; | done". | sillysaurusx wrote: | I used Python subprocess module for this. | | ... good luck, is my best advice. It's not straightforward to | handle edge cases. | marcodiego wrote: | Long time ago, a colleague of mine created "evenmoreutils" : | https://github.com/rudymatela/evenmoreutils | aendruk wrote: | See also the related announcement [1] on the most recent | "Volunteer Responsibility Amnesty Day" [2]. | | [1]: | https://joeyh.name/blog/entry/Volunteer_Responsibility_Amnes... | | [2]: https://www.volunteeramnestyday.net/ | mc4ndr3 wrote: | How does sponge compare with tee? | mftb wrote: | I have used vidir from this collection quite a bit. If you're a | vi person, it's makes it quite convenient to use vi/vim for | renaming whole directories full of files. | tails4e wrote: | I wrote a utility like ts before, called it teetime, was thrilled | with my pun. It was quiteand useful when piping stdout from a | compute heavy tool (multi hour EDA tool run) as you could see by | the delta time between logs what the most time consuming parts | were. | escot wrote: | Using `vipe` you can do things like: $ pbpaste | | vipe | pbcopy | | Which will open your editor so you can edit whatever is in your | clipboard. | IshKebab wrote: | Just realised what the pb stands for. Did they really not think | of clipboard? Who came up with the "clipboard" name? | Delk wrote: | Wikipedia says "clipboard" was coined by Larry Tesler (in the | 70's?) | zarzavat wrote: | The pasteboard, like many things in OS X, is from NextStep. | As for why they called it a pasteboard and not a clipboard, I | have no idea, presumably someone thought it would be more | descriptive. | [deleted] | BoneZone wrote: | I chuckled at pee | theandrewbailey wrote: | I outright laughed that its juxtaposed with sponge. | jchw wrote: | How might one use sponge in a way that shell redirection wouldn't | be more fully-featured? The best I can currently think of is that | it's less cumbersome to wrap (for things like sudo.) | JoshTriplett wrote: | Sponge exists for cases where shell redirection wouldn't work, | namely where you want the source and sink to be the same file. | If you write: somecmd < somefile | othercmd | | anothercmd > somefile | | the output redirection will truncate the file before it can get | read as input. | | Sponge "soaks up" all the output before writing any of it, so | that you can write pipelines like that: | somecmd < somefile | othercmd | anothercmd | sponge somefile | jchw wrote: | Thank you, I missed this bit of nuance. That indeed would be | useful, and now the example makes a lot more sense. | scbrg wrote: | This _can_ be done with regular shell redirection, even | though I wouldn 't recommend it. Easy to get wrong, and | fairly opaque: $ cat foo foo | bar baz $ ( rm foo && grep ba > foo ) < foo | $ cat foo bar baz $ | figital wrote: | here's a little wrapper around i made around "find" which i | always have to install on every new box i manage .... | | https://github.com/figital/fstring | | (just shows you more useful details about what is found) | eichin wrote: | heh. I use `chronic` all the time, `ifdata` in some scripts that | predate Linux switching to `ip`. I occasionally use `sponge` for | things but it's almost always an alternative to doing something | correctly :-) | | Looking at the other comments, I suspect one of the difficulties | in finding a new maintainer will be that lots of people use 2 or | 3 commands from it, but nobody uses the _same_ 2 or 3, and | actually caring about all of them is a big stretch... | suprjami wrote: | Have loved this collection for a long time. I use errno almost | daily. | moralestapia wrote: | >pee: tee standard input to pipes | | Nice tool, great name. | theteapot wrote: | Some of this looks useful, but a non exhaustive critique - from | non expert - of some of the rest: | | > chronic: runs a command quietly unless it fails | | Isn't that just `command >/dev/null`? | | > ifdata: get network interface info without parsing ifconfig | output | | `ip link show <if>`? | | > isutf8: check if a file or standard input is utf-8 | | `file` for files. For stdin, when is it not utf8 - unless you've | got some weird system configuration? | | > lckdo: execute a program with a lock held | | `flock`? | compsciphd wrote: | > > chronic: runs a command quietly unless it fails | | > Isn't that just `command >/dev/null`? | | no. that just shows your stderr, not stdout if it failed. and | you get stderr even if it doesn't fail. | ninkendo wrote: | > > chronic: runs a command quietly unless it fails > Isn't | that just `command >/dev/null`? | | Often times you want to run a command silently (like in a build | script), but if it fails with a nonzero exit status, you want | to then display not only the stderr but the stdout as well. | I've written makefile hacks in the past that do this to silence | overly-chatty compilers where we don't really care what it's | outputting unless it fails, in which case we want all the | output. It would've been nice to have this tool at the time to | avoid reinventing it. | arendtio wrote: | I guess that chronic doesn't just show stderr, but also stdout | if the command fails. If I am not mistaken, your example would | hide the stdout output, even when the command fails. ___________________________________________________________________ (page generated 2022-04-15 23:00 UTC)