Live data from Hacker News

Unix tricks

mmb.pcb.ub.es

121–130 of 232 posts

Re: Unix tricks

#121
post #5

1) `pgrep` is a standard utility that does what his `psgrep` does and much much more. 2) htop is a cpu and memory hog -- every time I've used it I noticed it takes 6+% CPU time 3) there's an awk trick to do the `sort | uniq` recommendation that works on 10+GB files (single pass): awk '!x[$0]++' 4) Passwordless keys are dangerous -- use ssh-agent to save the password of the keys

3) if all the lines of the 10+GB file are actually unique, wouldn't awk keep the whole file in RAM? For files larger than my RAM could this leave my system unresponsive because it's thrashing on swap?

Yes it will, and a bit (read: a lot) more than 10GB as it needs to store the contents of variable x in a hash table (with the corresponding hash key and value of the counter). There's no other magic way it can 'know' whether a particular line has been seen before. You can't rely on hash keys alone as the hashes aren't guaranteed to be unique.

For files with relatively few duplicates it's going to be a lot slower than sort | uniq.

Trying it on a 128MB file (nowhere near enough time to test a 10GB file) filled with lines of 7 random upper case characters[1] (so hardly any duplicates):-

    $ wc -l x.out
    16777216 x.out
    
    $ time ( sort x.out | uniq ) | wc -l
    16759719

    real    0m17.982s
    user    0m42.575s
    sys     0m0.876s
    
    $ time ( sort -u x.out ) | wc -l
    16759719

    real    0m20.582s
    user    0m43.775s
    sys     0m0.688s
Not much difference between "sort | uniq" and "sort -u".

As for the awk method:-

    $ time awk '!x[$0]++' x.out | wc -l
    
has been running for more than 20 minutes and still hasn't returned. For that 128MB file the awk process is also using 650MB of memory (according to ps). Will check up on it later (have to go out now).

This Linux machine has ~16GB of memory so the file was going to be completed cached in memory before the first test. All things considered equal the awk method will be roughly O(n) (e.g. linear against file size) and sort/uniq will be O(n log n). So, theoretically, the awk method will eventually surpass the sort method because it's having to do less work (it's only checking for a previously seen key rather than sorting the entire file) but I'm not sure the crossover will be anywhere useful if the file doesn't contain many duplicates.

Repeating it for a file containing lots of duplicates (same 128MB file size but contents are only the 7 letter words consisting of A or B, so only 128 possible entries):-

    $ time awk '!x[$0]++' y.out | wc -l
    128
    
    real    0m1.207s
    user    0m1.192s
    sys     0m0.016s
    
    $ time ( sort y.out | uniq ) | wc -l
    128

    real    0m14.320s
    user    0m31.414s
    sys     0m0.428s
    
    $ time ( sort -u y.out | uniq ) | wc -l
    128
    
    real    0m12.638s
    user    0m30.366s
    sys     0m0.188s
Notice that "sort -u" doesn't do anything clever for files with lots of duplicates.

So awk is much faster for files with lots of duplicates. No great surprises. When I get a chance I'll repeat it for a 1GB file and a 10GB file (with lots of duplicates otherwise the awk version will take far too long).

1. Example contents:-

EPQKHPH DLJCROB WICVGQY MHWTPSR HMPNECN

Re: Unix tricks

#122

Earlier quoted context omitted.

rsync is slow if the data is not already on the destination. tar over ssh is fast, and tar over socketpipe is even faster but not encrypted. I'm not aware of any attributes that tar doesn't preserve.

How so? Also, I find that if I'm going to copy the data once, I'm often going to copy it twice, or which to get a more up to date version of it at a later time. Rsync clearly wins in these cases. Finally, from the compress flag on rsync: Note that this option typically achieves better compression ratios than can be achieved by using a compressing remote shell or a compressing transport because it takes advantage of t…

Rsync is brilliant and useful but gets very slow when you apply it outside of its sweet-spot.

Remember: Rsync trades CPU and disk i/o (lots of disk i/o) for network bandwidth.

In the pathological case "thousands of tiny files over a fast network" it can easily be orders of magnitude slower than a straight tar.

Re: Unix tricks

#123

'!!:n' selects the nth argument of the last command, and '!$' the last arg A lot of people know about "!$" (which is shorthand for !!:$), but that's just the tip of Bash's history expansion. I use these things all the time. One of my favorite keystroke savers is adding :h, the head modifier, to !$. For example: $ cp file.txt /some/annoyingly/deep/target/directory/other.txt $ cd !$:h $ pwd # => /some/annoyingly/deep/t…

That first example is great, thanks. I run into that all the time. Up until now I've been doing this:

$ cp file.txt /some/annoyingly/deep/target/directory/other.txt

$ cd !$ (No such file or directory)

(up arrow and then backspace to directory)

Re: Unix tricks

#124
post #113

- Use 'apt-file' to see which package provides that file you're missing Ummm, "apt-" isn't a "Unix trick..." It's specific to linux distros which use the "Aptitude" package manager. Linux != Unix

Aptitude is just a front-end to APT. And APT (package tool) is just an interface to dpkg or RPM (package managers).

Re: Unix tricks

#125

'!!:n' selects the nth argument of the last command, and '!$' the last arg A lot of people know about "!$" (which is shorthand for !!:$), but that's just the tip of Bash's history expansion. I use these things all the time. One of my favorite keystroke savers is adding :h, the head modifier, to !$. For example: $ cp file.txt /some/annoyingly/deep/target/directory/other.txt $ cd !$:h $ pwd # => /some/annoyingly/deep/t…

Alt + . – use the last word of the previous command.

    $ cp file.txt /some/annoyingly/deep/target/directory/other.txt
    $ cd then press Alt + .
    $ pwd # => /some/annoyingly/deep/target/directory

Re: Unix tricks

#126

'!!:n' selects the nth argument of the last command, and '!$' the last arg A lot of people know about "!$" (which is shorthand for !!:$), but that's just the tip of Bash's history expansion. I use these things all the time. One of my favorite keystroke savers is adding :h, the head modifier, to !$. For example: $ cp file.txt /some/annoyingly/deep/target/directory/other.txt $ cd !$:h $ pwd # => /some/annoyingly/deep/t…

Another nice ending is `:p` to print the command instead of executing it. I use this if I'm doing something complicated and I want to make sure it's right. Or if I'm saying `!-n:foo` with n>2. Then just up-arrow and enter to run it for real.

Re: Unix tricks

#127
post #65

Learn to use your shell's globbing features instead of overusing find. In zsh, you can do 'print -l /*.(c|cc|h|hh)' for example (I'm sure bash has an equivalent).

does that work for say 2143789 files?

Re: Unix tricks

#128
post #125

'!!:n' selects the nth argument of the last command, and '!$' the last arg A lot of people know about "!$" (which is shorthand for !!:$), but that's just the tip of Bash's history expansion. I use these things all the time. One of my favorite keystroke savers is adding :h, the head modifier, to !$. For example: $ cp file.txt /some/annoyingly/deep/target/directory/other.txt $ cd !$:h $ pwd # => /some/annoyingly/deep/t…

Alt + . – use the last word of the previous command. $ cp file.txt /some/annoyingly/deep/target/directory/other.txt $ cd then press Alt + . $ pwd # => /some/annoyingly/deep/target/directory

No, that gives the last word, as you say, we want the dirname of the last word.

    $ echo foo/bar
    foo/bar
    $ echo !$ !$:h
    foo/bar foo

Re: Unix tricks

#129

'!!:n' selects the nth argument of the last command, and '!$' the last arg A lot of people know about "!$" (which is shorthand for !!:$), but that's just the tip of Bash's history expansion. I use these things all the time. One of my favorite keystroke savers is adding :h, the head modifier, to !$. For example: $ cp file.txt /some/annoyingly/deep/target/directory/other.txt $ cd !$:h $ pwd # => /some/annoyingly/deep/t…

Another nice ending is `:p` to print the command instead of executing it. I use this if I'm doing something complicated and I want to make sure it's right. Or if I'm saying `!-n:foo` with n>2. Then just up-arrow and enter to run it for real.

I use magic-space for that in my inputrc:

  $if Bash
    Space: magic-space
  $endif
Basically does the same thing as :p, but after a space instead of enter.

Edit: fixed formatting.

Re: Unix tricks

#130

'!!:n' selects the nth argument of the last command, and '!$' the last arg A lot of people know about "!$" (which is shorthand for !!:$), but that's just the tip of Bash's history expansion. I use these things all the time. One of my favorite keystroke savers is adding :h, the head modifier, to !$. For example: $ cp file.txt /some/annoyingly/deep/target/directory/other.txt $ cd !$:h $ pwd # => /some/annoyingly/deep/t…

A sometimes handy addition to the s modifier is g, which replaces all instances of the pattern instead of just the first.

    $ echo "foo foo"
    foo foo
    $ echo !!:s/foo/bar
    echo echo "bar foo"
    echo bar foo

    $ echo "foo foo"
    foo foo
    $ echo !!:gs/foo/bar
    echo echo "bar bar"
    echo bar bar
Post reply on HN