Best way to reimplement Unix pipes



  • I really don't know what the person behind this was thinking:

    LIST_FILES=`ls $SOME_DIR`
    for files in $LIST_FILES; do
        echo $files >> foo.txt
    done

    The worst part is that it doesn't have into account filenames with blank spaces.



  •  Isn't Unix aptly described as a series of pipes?

     



  • Seems they were after this:

    ls $SOME_DIR >> foo.txt

    Did they think ">>" only works with echo?



  •  Maybe they just wanted to mess up the space characters.



  • Obviously they should have done:

     ls $SOME_DIR | xargs -n 1 echo >> foo.txt



  • @dhromed said:

     Isn't Unix aptly described as a series of pipes?

     

     

    No, that'll be the internet. 



  • @ubersoldat said:

    The worst part is that it doesn't have into account filenames with blank spaces.

    Technically it only messes up spaces if there are multiple space characters in a row or if there are non-space whitespace characters.



  • @dhromed said:

    Isn't Unix aptly described as a series of pipes?

    Aren't your neigborhood "pool parties" aptly described as a series of hoses?



  • @morbiuswilters said:

    series of hoses
    That's not the plural of ho.



  • @ubersoldat said:

    The worst part is that it doesn't have into account filenames with blank spaces.
     

    Huh?



  • @blakeyrat said:

    @ubersoldat said:

    The worst part is that it doesn't have into account filenames with blank spaces.
     

    Huh?

    Stupid Windozo lo$er, you probably didn't even realize filenames could have spaces or new-lines or BEL characters in them.  See, Unix shells do word splitting.  So if the filename has a space, that gets saved to the variable "files".  Now, he's calling doing 'echo $files'.  The shell substitutes $files for the content of the variable, then it does word-splitting, so if the variable files contains whitespace, the shell splits that whitespace into individual arguments.  If your filename is "foo bar.txt", then your shell calls echo with two arguments: 'foo' and 'bar.txt'.  If it's only a single space, no biggie, because echo will put a space between each argument it echos out.  However, if your filename is "foo  bar.txt" (two spaces, CS might eat that and only show one) or "foo\tbar.txt" or "foo\nbar.txt", the shell will split all of those into two arguments for echo, which will echo them out with one space between them.

     

    In short, you should always quote strings when used in arguments.  Quoting treats the string as a single argument, keeping it from doing word-splitting.  So 'echo "$files" >> foo.txt' would have been the proper way.



  • @morbiuswilters said:

    In short, you should always quote strings when used in arguments.  Quoting treats the string as a single argument, keeping it from doing word-splitting.  So 'echo "$files" >> foo.txt' would have been the proper way.
    No!  Bad!  Stop lying to Windows users to amuse yourself.  The problem is actually using [code]ls[/code] with [code]for ... in[/code] instead of just using a glob directly:

    bstorer@Heimdall ~/gay morb
    $ ls
    morb is a fag
    

    bstorer@Heimdall ~/gay morb
    $ LIST_FILES=ls $SOME_DIR

    bstorer@Heimdall ~/gay morb
    $ for files in $LIST_FILES; do echo "$files"; done
    morb
    is
    a
    fag

    bstorer@Heimdall ~/gay morb
    $ for files in *; do echo $files; done
    morb is a fag



  •  I <3 U



  • @bstorer said:

    $ ls
    morb is a fag

    Hmm.. using directory ordering rather than alphabetical?  I hate you.

     

    @bstorer said:

    bstorer@Heimdall ~/gay morb
    $ for files in *; do echo $files; done
    morb is a fag

    echo should be inserting a newline after each of those.  Either your echo is non-standard or you made this whole thing up to make me look like a fag.



  • @morbiuswilters said:

     

    echo should be inserting a newline after each of those.  Either your echo is non-standard or you made this whole thing up to make me look like a fag.

    You misunderstand me.  Let me offer a clearer example:

    [~/gay morb]$ ls -lb
    total 0
    -rw-rw-r-- 1 bstorer pg588160 0 Mar 24 22:03 i\ love\ you\ morb
    -rw-rw-r-- 1 bstorer pg588160 0 Mar 24 21:58 morb\ is\ a\ fag
    -rw-rw-r-- 1 bstorer pg588160 0 Mar 24 22:02 morb\ loves\ the\ cock
    

    [~/gay morb]$ for file in ls *; do echo "$file"; done
    i
    love
    you
    morb
    morb
    is
    a
    fag
    morb
    loves
    the
    cock

    [~/gay morb]$ for file in *; do echo $file; done
    i love you morb
    morb is a fag
    morb loves the cock

    See what I'm talking about? No amount of quoting in the [code]echo[/code] command will make it work because the results of the backtick expansion are split on whitespace anyway. Now, admittedly, you're right, [code]echo[/code] should still have its argument quoted:

    [~/gay morb]$ touch morb\'s\ \ withered\ \ penis
    

    [~/gay morb]$ ls -lb
    total 0
    -rw-rw-r-- 1 bstorer pg588160 0 Mar 24 22:03 i\ love\ you\ morb
    -rw-rw-r-- 1 bstorer pg588160 0 Mar 24 21:58 morb\ is\ a\ fag
    -rw-rw-r-- 1 bstorer pg588160 0 Mar 24 22:02 morb\ loves\ the\ cock
    -rw-rw-r-- 1 bstorer pg588160 0 Mar 24 22:05 morb's\ \ withered\ \ penis

    [~/gay morb]$ for file in *; do echo $file; done
    i love you morb
    morb is a fag
    morb loves the cock
    morb's withered penis

    [~/gay morb]$ for file in *; do echo "$file"; done
    i love you morb
    morb is a fag
    morb loves the cock
    morb's withered penis



  • @bstorer said:

    You misunderstand me.  Let me offer a clearer example:
     

    I feel there is something insinuated by your code... but I can't quite put my finger on it.



  • @Thief^ said:

    Seems they were after this:

    ls $SOME_DIR >> foo.txt

    Did they think ">>" only works with echo?

     

    Probably. Similar to how some people always do

    cd \

    cd some\other\dir

     



  • @dhromed said:

    I feel there is something insinuated by your code... but I can't quite put my finger on it.

    I don't think you want to put your finger on it... unless you're into that kind of thing of course.



  • /tmp/x$ ls -l
    total 0
    -rw-r--r-- 1 ais523 ais523 0 2010-03-25 13:01 foo.txt
    -rw-r--r-- 1 ais523 ais523 0 2010-03-25 13:01 t 1
    -rw-r--r-- 1 ais523 ais523 0 2010-03-25 13:01 t  2
    -rw-r--r-- 1 ais523 ais523 0 2010-03-25 13:01 t3
    /tmp/x$ env IFS="`printf "\n"`" X="`ls`" sh -c 'for a in $X; do echo "$a"; done'
    foo.txt t 1 t 2 t3

    The technique written in the code could work; what's necessary is setting (temporarily, I hope!) IFS to newline rather than space so that for doesn't try to split on spaces, and quoting the backticks so that they don't try to split on spaces either. Of course, this is ridiculous.

    TRWTF is that the correct way to do what that code was probably meant to do is "ls $SOMEDIR >> foo.txt" (or maybe even "ls $somedir > foo.txt", depending exactly on what the code meant to do). The clearest way to do what it actually does (replacing characters in $IFS with newlines in ls's output, squeezing duplicates), if that was intended behaviour, is probably like this:

    /tmp/x$ ls $SOMEDIR | tr -s "$IFS" "[\n*]" >> foo.txt
    /tmp/x$ cat foo.txt
    foo.txt
    t
    1
    t
    2
    t3

    although even that doesn't allow for the fact that $SOMEDIR might be the current directory and foo.txt might not already exist (in which case, foo.txt might be shown in the listing with this method when it definitely wouldn't with the other method, depending on whether the shell creates the file faster or slower than ls runs).



  • @morbiuswilters said:

    @bstorer said:

    $ ls
    morb is a fag

    Hmm.. using directory ordering rather than alphabetical?  I hate you.

     

    So you prefer "a fag is morb"? I don't find it much of an improvement.



  • @ubersoldat said:

    The worst part is that it doesn't have into account filenames with blank spaces.

    What about non-blank spaces?


  • @Adriano said:

    @morbiuswilters said:

    @bstorer said:

    $ ls
    morb is a fag

    Hmm.. using directory ordering rather than alphabetical?  I hate you.

     

    So you prefer "a fag is morb"? I don't find it much of an improvement.

    Thinks it's fucking great, Yoda does.



Log in to reply