Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #72267 > unrolled thread

Multi-line commands with 'python -c'

Started byChris Angelico <rosuav@gmail.com>
First post2014-05-30 10:52 +1000
Last post2014-06-01 20:43 +0000
Articles 15 — 6 participants

Back to article view | Back to comp.lang.python


Contents

  Multi-line commands with 'python -c' Chris Angelico <rosuav@gmail.com> - 2014-05-30 10:52 +1000
    Re: Multi-line commands with 'python -c' Rustom Mody <rustompmody@gmail.com> - 2014-05-29 23:04 -0700
      Re: Multi-line commands with 'python -c' Rustom Mody <rustompmody@gmail.com> - 2014-05-29 23:45 -0700
        Re: Multi-line commands with 'python -c' Rustom Mody <rustompmody@gmail.com> - 2014-05-29 23:54 -0700
          Re: Multi-line commands with 'python -c' Peter Otten <__peter__@web.de> - 2014-05-30 09:33 +0200
        Re: Multi-line commands with 'python -c' Terry Reedy <tjreedy@udel.edu> - 2014-05-30 11:29 -0400
      Re: Multi-line commands with 'python -c' Chris Angelico <rosuav@gmail.com> - 2014-05-30 17:20 +1000
        Re: Multi-line commands with 'python -c' Rustom Mody <rustompmody@gmail.com> - 2014-05-30 05:47 -0700
          Re: Multi-line commands with 'python -c' Chris Angelico <rosuav@gmail.com> - 2014-05-30 22:58 +1000
    Re: Multi-line commands with 'python -c' Duncan Booth <duncan.booth@invalid.invalid> - 2014-05-30 21:11 +0000
      Re: Multi-line commands with 'python -c' Devin Jeanpierre <jeanpierreda@gmail.com> - 2014-05-30 14:42 -0700
      Re: Multi-line commands with 'python -c' Chris Angelico <rosuav@gmail.com> - 2014-05-31 07:47 +1000
        Re: Multi-line commands with 'python -c' Duncan Booth <duncan.booth@invalid.invalid> - 2014-05-31 16:41 +0000
          Re: Multi-line commands with 'python -c' Peter Otten <__peter__@web.de> - 2014-05-31 19:11 +0200
            Re: Multi-line commands with 'python -c' Duncan Booth <duncan.booth@invalid.invalid> - 2014-06-01 20:43 +0000

#72267 — Multi-line commands with 'python -c'

FromChris Angelico <rosuav@gmail.com>
Date2014-05-30 10:52 +1000
SubjectMulti-line commands with 'python -c'
Message-ID<mailman.10468.1401411146.18130.python-list@python.org>
Since lines are so critical to Python syntax, I'm a little surprised
there's no majorly obvious solution to this... or maybe I'm just
blind.

Problem: Translate this into a shell one-liner:

import os
for root, dirs, files in os.walk("."):
    if len(dirs + files) == 1: print(root)

Solution 1: SyntaxError

python -c 'import os; for root, dirs, files in os.walk("."): if
len(dirs + files) == 1: print(root)'

You can't put a 'for' statement after an 'import' with just a semicolon.

Solution 2: SyntaxError

python -c 'import os\nfor root, dirs, files in os.walk("."): if
len(dirs + files) == 1: print(root)'

You can't put a backslash escape into your code like that! Makes no sense.

Solution 3: Silence

python -c 'import os' -c 'for root, dirs, files in os.walk("."): if
len(dirs + files) == 1: print(root)'

Haven't dug into exactly what this does, but the docs say that -c
terminates the option list, so I would guess that the second -c and
its arg get passed to the script.

Solution 4: Rely on the shell's ability to pass newlines inside arguments

$ python -c 'import os
> for root, dirs, files in os.walk("."):
>     if len(dirs + files) == 1: print(root)
> '

That works, but at that point, you aren't writing a one-liner any
more. It's also fiddly to edit.

Is there a better way to put multiple virtual lines into a 'python -c' command?

ChrisA

[toc] | [next] | [standalone]


#72278

FromRustom Mody <rustompmody@gmail.com>
Date2014-05-29 23:04 -0700
Message-ID<25135194-b9cb-4942-bead-c1bdf72923ee@googlegroups.com>
In reply to#72267
On Friday, May 30, 2014 6:22:24 AM UTC+5:30, Chris Angelico wrote:
> Since lines are so critical to Python syntax, I'm a little surprised
> there's no majorly obvious solution to this... or maybe I'm just
> blind.

> Problem: Translate this into a shell one-liner:

> import os
> for root, dirs, files in os.walk("."):
>     if len(dirs + files) == 1: print(root)

I would have thought this would work:

python -m os -c 'for root, dirs, files in os.walk("."): if len(dirs + files) == 1: print(root)'

Unfortunately doesn't 
But did show up a small doc-bug:

This fact is not documented in 
$ man python
but is documented in 
$ python -h

Anyways...

I thought when one signs up for python one has to sign an affidavit
saying:
"I shall not write one-liners\n" * 100

[toc] | [prev] | [next] | [standalone]


#72280

FromRustom Mody <rustompmody@gmail.com>
Date2014-05-29 23:45 -0700
Message-ID<bc4414a4-ff30-4a72-9b86-2adb3e3c9578@googlegroups.com>
In reply to#72278
On Friday, May 30, 2014 11:34:36 AM UTC+5:30, Rustom Mody wrote:
> On Friday, May 30, 2014 6:22:24 AM UTC+5:30, Chris Angelico wrote:
> > Since lines are so critical to Python syntax, I'm a little surprised
> > there's no majorly obvious solution to this... or maybe I'm just
> > blind.

> > Problem: Translate this into a shell one-liner:


> > import os
> > for root, dirs, files in os.walk("."):
> >     if len(dirs + files) == 1: print(root)

Heres a (poooor) approx

$ python -c 'import os, pprint; pprint.pprint ([ r for r, d, f in os.walk(".") if len(d+f) != 1])'


Mysterious that print after a ; is fine whereas for is not



> Anyways...

> I thought when one signs up for python one has to sign an affidavit
> saying:
> "I shall not write one-liners\n" * 100

I hope youve signed it by now <wink>

[toc] | [prev] | [next] | [standalone]


#72281

FromRustom Mody <rustompmody@gmail.com>
Date2014-05-29 23:54 -0700
Message-ID<1243054d-84af-46d5-ae7e-5882f35c0b69@googlegroups.com>
In reply to#72280
On Friday, May 30, 2014 12:15:46 PM UTC+5:30, Rustom Mody wrote:
> Heres a (poooor) approx
> 
> $ python -c 'import os, pprint; pprint.pprint ([ r for r, d, f in os.walk(".") if len(d+f) != 1])'

Without pprint: (pooor)

python -c 'import os; print "\n".join([ r for r, d, f in os.walk(".") if len(d+f) != 1])'

Or (poor)

python -c 'from os import walk; print "\n".join([ r for r, d, f in walk(".") if len(d+f) != 1])'

[toc] | [prev] | [next] | [standalone]


#72287

FromPeter Otten <__peter__@web.de>
Date2014-05-30 09:33 +0200
Message-ID<mailman.10480.1401435220.18130.python-list@python.org>
In reply to#72281
Rustom Mody wrote:

> On Friday, May 30, 2014 12:15:46 PM UTC+5:30, Rustom Mody wrote:
>> Heres a (poooor) approx
>> 
>> $ python -c 'import os, pprint; pprint.pprint ([ r for r, d, f in
>> os.walk(".") if len(d+f) != 1])'
> 
> Without pprint: (pooor)
> 
> python -c 'import os; print "\n".join([ r for r, d, f in os.walk(".") if
> len(d+f) != 1])'
> 
> Or (poor)
> 
> python -c 'from os import walk; print "\n".join([ r for r, d, f in
> walk(".") if len(d+f) != 1])'

If there are a lot of matching folders:

$ python -c 'import os, sys; sys.stdout.writelines(p + "\n" for p, f, n in 
os.walk(".") if len(n+f) == 1)'

With a little help from the shell:

$ echo -e "import os\nfor p, f, n in os.walk('.'):\n if len(f+n) == 1: 
print(p)" | python

[toc] | [prev] | [next] | [standalone]


#72304

FromTerry Reedy <tjreedy@udel.edu>
Date2014-05-30 11:29 -0400
Message-ID<mailman.10488.1401463814.18130.python-list@python.org>
In reply to#72280
On 5/30/2014 2:45 AM, Rustom Mody wrote:

> $ python -c 'import os, pprint; pprint.pprint ([ r for r, d, f in os.walk(".") if len(d+f) != 1])'
>
> Mysterious that print after a ; is fine whereas for is not

Not at all. Simple statememts can follow ; or :, compound statements cannot.

-- 
Terry Jan Reedy

[toc] | [prev] | [next] | [standalone]


#72284

FromChris Angelico <rosuav@gmail.com>
Date2014-05-30 17:20 +1000
Message-ID<mailman.10478.1401434433.18130.python-list@python.org>
In reply to#72278
On Fri, May 30, 2014 at 4:04 PM, Rustom Mody <rustompmody@gmail.com> wrote:
> I thought when one signs up for python one has to sign an affidavit
> saying:
> "I shall not write one-liners\n" * 100

Certainly not. I write all my list comps on one line!

*ducking for cover*

ChrisA

[toc] | [prev] | [next] | [standalone]


#72295

FromRustom Mody <rustompmody@gmail.com>
Date2014-05-30 05:47 -0700
Message-ID<a5dd8a43-58e2-4fb7-b2c2-c62601bce3d5@googlegroups.com>
In reply to#72284
On Friday, May 30, 2014 12:50:31 PM UTC+5:30, Chris Angelico wrote:
> On Fri, May 30, 2014 at 4:04 PM, Rustom Mody wrote:
> > I thought when one signs up for python one has to sign an affidavit
> > saying:
> > "I shall not write one-liners\n" * 100

> Certainly not. I write all my list comps on one line!

> *ducking for cover*

Heres a more vile misuse of python3's print-as-function + list-comp-as-for:

python3 -c 'from os import walk; [print(r) for r, d, f in walk(".") if len(d+f) == 1]'

Well if C programmers can use ',' as one-line ';' and '?:' as one-line if
why not python also?

[To noobs who are reading: Dont do this!]

[toc] | [prev] | [next] | [standalone]


#72297

FromChris Angelico <rosuav@gmail.com>
Date2014-05-30 22:58 +1000
Message-ID<mailman.10484.1401454700.18130.python-list@python.org>
In reply to#72295
On Fri, May 30, 2014 at 10:47 PM, Rustom Mody <rustompmody@gmail.com> wrote:
> On Friday, May 30, 2014 12:50:31 PM UTC+5:30, Chris Angelico wrote:
>> On Fri, May 30, 2014 at 4:04 PM, Rustom Mody wrote:
>> > I thought when one signs up for python one has to sign an affidavit
>> > saying:
>> > "I shall not write one-liners\n" * 100
>
>> Certainly not. I write all my list comps on one line!
>
>> *ducking for cover*
>
> Heres a more vile misuse of python3's print-as-function + list-comp-as-for:
>
> python3 -c 'from os import walk; [print(r) for r, d, f in walk(".") if len(d+f) == 1]'
>
> Well if C programmers can use ',' as one-line ';' and '?:' as one-line if
> why not python also?
>
> [To noobs who are reading: Dont do this!]

I actually crafted the exact same vile misuse, prior to asking the question.

https://lists.debian.org/debian-user/2014/05/msg02019.html

Modulo trivialities like whitespace and the from-import, it's exactly
the same as your version.

Incidentally, C's ?: operator maps to Python's ternary if/else
operator, which most definitely is valid in a one-liner. So it's just
the semicolon that you're looking at. In C, you can combine any two
statements onto one line; in Python, certain statements may not follow
a semicolon. So it's not really ; and ?: that are the point here, but
that Python, with its stricter rules about newlines (as opposed to
"any whitespace"), doesn't seem to have a convenient notation for
putting multiple lines into a -c command.

ChrisA

[toc] | [prev] | [next] | [standalone]


#72319

FromDuncan Booth <duncan.booth@invalid.invalid>
Date2014-05-30 21:11 +0000
Message-ID<XnsA33DE1B7E35C5duncanbooth@127.0.0.1>
In reply to#72267
Chris Angelico <rosuav@gmail.com> wrote:

> Problem: Translate this into a shell one-liner:
> 
> import os
> for root, dirs, files in os.walk("."):
>     if len(dirs + files) == 1: print(root)
> 

This is one area where Windows seems to do better than Linux shells:

PS C:\python33> python -c "import os`nfor root, dirs, files in os.walk('.'):`n    if len(dirs + files) == 1: print(root)`n"
.\Doc
.\Lib\concurrent\__pycache__
.\Lib\curses\__pycache__
...

The `n shell escaped newline is interpreted well before Python runs.

Also the multiline version works and in Powershell ISE up-arrow pulls it back as a 
single unit for easy editing:

PS C:\python33> python -c @"
import os
for root, dirs, files in os.walk('.'):
    if len(dirs + files) == 1: print(root)
"@
.\Doc
.\Lib\concurrent\__pycache__
.\Lib\curses\__pycache__
... and so on ...


-- 
Duncan Booth

[toc] | [prev] | [next] | [standalone]


#72320

FromDevin Jeanpierre <jeanpierreda@gmail.com>
Date2014-05-30 14:42 -0700
Message-ID<mailman.10498.1401486177.18130.python-list@python.org>
In reply to#72319
In unix shells you can literally use a new line. Or is that only bash?

-- Devin

On Fri, May 30, 2014 at 2:11 PM, Duncan Booth
<duncan.booth@invalid.invalid> wrote:
> Chris Angelico <rosuav@gmail.com> wrote:
>
>> Problem: Translate this into a shell one-liner:
>>
>> import os
>> for root, dirs, files in os.walk("."):
>>     if len(dirs + files) == 1: print(root)
>>
>
> This is one area where Windows seems to do better than Linux shells:
>
> PS C:\python33> python -c "import os`nfor root, dirs, files in os.walk('.'):`n    if len(dirs + files) == 1: print(root)`n"
> .\Doc
> .\Lib\concurrent\__pycache__
> .\Lib\curses\__pycache__
> ...
>
> The `n shell escaped newline is interpreted well before Python runs.
>
> Also the multiline version works and in Powershell ISE up-arrow pulls it back as a
> single unit for easy editing:
>
> PS C:\python33> python -c @"
> import os
> for root, dirs, files in os.walk('.'):
>     if len(dirs + files) == 1: print(root)
> "@
> .\Doc
> .\Lib\concurrent\__pycache__
> .\Lib\curses\__pycache__
> ... and so on ...
>
>
> --
> Duncan Booth
> --
> https://mail.python.org/mailman/listinfo/python-list

[toc] | [prev] | [next] | [standalone]


#72322

FromChris Angelico <rosuav@gmail.com>
Date2014-05-31 07:47 +1000
Message-ID<mailman.10500.1401486463.18130.python-list@python.org>
In reply to#72319
On Sat, May 31, 2014 at 7:42 AM, Devin Jeanpierre
<jeanpierreda@gmail.com> wrote:
> In unix shells you can literally use a new line. Or is that only bash?

You can in bash, I know, but it's fiddly to type it; and more
importantly, it's not a good point in the "this is cleaner than a
series of pipes" argument. My primary recommendation, of course, was a
three-line script saved as an actual file, but for a more direct
parallel to the pipe-it-three-ways model, I wanted to use -c.

ChrisA

[toc] | [prev] | [next] | [standalone]


#72341

FromDuncan Booth <duncan.booth@invalid.invalid>
Date2014-05-31 16:41 +0000
Message-ID<XnsA33EAA18C31A6duncanbooth@127.0.0.1>
In reply to#72322
Chris Angelico <rosuav@gmail.com> wrote:

> On Sat, May 31, 2014 at 7:42 AM, Devin Jeanpierre
><jeanpierreda@gmail.com> wrote:
>> In unix shells you can literally use a new line. Or is that only 
bash?
> 
> You can in bash, I know, but it's fiddly to type it; and more
> importantly, it's not a good point in the "this is cleaner than a
> series of pipes" argument. My primary recommendation, of course, was a
> three-line script saved as an actual file, but for a more direct
> parallel to the pipe-it-three-ways model, I wanted to use -c.

and you also wrote originally that it's fiddly to edit. I think that 
Windows Powershell has (at least in the current ISE command line) got 
the editing a bit better. It's a minor difference though and it has 
taken Microsoft about 30 years to get to that point.

What may be a larger difference, or may just be my lack of Linux-foo, is 
this:

PS C:\python33> $script = @"
import os
for root, dirs, files in os.walk("."):
    if len(dirs + files) == 1: print(root)
"@

PS C:\python33> python -c $script
.\Doc
.\Lib\concurrent\__pycache__
.\Lib\curses\__pycache__
...

which is a style I've found useful for example when running a group of 
related timeit.py commands as I can put things like multi-line setup 
statements in a variable and then have a simpler command to repeat.

But bash as far as I can won't let me do that:

$ script='import os 
for root, dirs, files in os.walk("."):
    if len(dirs + files) == 1: print(root)
'
$ python -c $script
  File "<string>", line 1
    import
         ^
SyntaxError: invalid syntax


-- 
Duncan Booth

[toc] | [prev] | [next] | [standalone]


#72343

FromPeter Otten <__peter__@web.de>
Date2014-05-31 19:11 +0200
Message-ID<mailman.10511.1401556283.18130.python-list@python.org>
In reply to#72341
Duncan Booth wrote:

> Chris Angelico <rosuav@gmail.com> wrote:
> 
>> On Sat, May 31, 2014 at 7:42 AM, Devin Jeanpierre
>><jeanpierreda@gmail.com> wrote:
>>> In unix shells you can literally use a new line. Or is that only
> bash?
>> 
>> You can in bash, I know, but it's fiddly to type it; and more
>> importantly, it's not a good point in the "this is cleaner than a
>> series of pipes" argument. My primary recommendation, of course, was a
>> three-line script saved as an actual file, but for a more direct
>> parallel to the pipe-it-three-ways model, I wanted to use -c.
> 
> and you also wrote originally that it's fiddly to edit. I think that
> Windows Powershell has (at least in the current ISE command line) got
> the editing a bit better. It's a minor difference though and it has
> taken Microsoft about 30 years to get to that point.
> 
> What may be a larger difference, or may just be my lack of Linux-foo, is
> this:
> 
> PS C:\python33> $script = @"
> import os
> for root, dirs, files in os.walk("."):
>     if len(dirs + files) == 1: print(root)
> "@
> 
> PS C:\python33> python -c $script
> .\Doc
> .\Lib\concurrent\__pycache__
> .\Lib\curses\__pycache__
> ...
> 
> which is a style I've found useful for example when running a group of
> related timeit.py commands as I can put things like multi-line setup
> statements in a variable and then have a simpler command to repeat.
> 
> But bash as far as I can won't let me do that:
> 
> $ script='import os
> for root, dirs, files in os.walk("."):
>     if len(dirs + files) == 1: print(root)
> '
> $ python -c $script
>   File "<string>", line 1
>     import
>          ^
> SyntaxError: invalid syntax
 
$ script='import os
> for root, dirs, files in os.walk("."):
>     if len(dirs + files) == 1:
>         print(root)
> '
$ python3 -c "$script"
.
./heureka

$ python3 -c 'import sys; print(sys.argv)' $script
['-c', 'import', 'os', 'for', 'root,', 'dirs,', 'files', 'in', 
'os.walk("."):', 'if', 'len(dirs', '+', 'files)', '==', '1:', 'print(root)']
$ python3 -c 'import sys; print(sys.argv)' "$script"
['-c', 'import os\nfor root, dirs, files in os.walk("."):\n    if len(dirs + 
files) == 1:\n        print(root)\n']


[toc] | [prev] | [next] | [standalone]


#72383

FromDuncan Booth <duncan.booth@invalid.invalid>
Date2014-06-01 20:43 +0000
Message-ID<XnsA33ED0FD114E8duncanbooth@127.0.0.1>
In reply to#72343
Peter Otten <__peter__@web.de> wrote:

> Duncan Booth wrote:
> 
>> Chris Angelico <rosuav@gmail.com> wrote:
>> 
>>> On Sat, May 31, 2014 at 7:42 AM, Devin Jeanpierre
>>><jeanpierreda@gmail.com> wrote:
>>>> In unix shells you can literally use a new line. Or is that only
>> bash?
>>> 
>>> You can in bash, I know, but it's fiddly to type it; and more
>>> importantly, it's not a good point in the "this is cleaner than a
>>> series of pipes" argument. My primary recommendation, of course, was
>>> a three-line script saved as an actual file, but for a more direct
>>> parallel to the pipe-it-three-ways model, I wanted to use -c.
>> 
>> and you also wrote originally that it's fiddly to edit. I think that
>> Windows Powershell has (at least in the current ISE command line) got
>> the editing a bit better. It's a minor difference though and it has
>> taken Microsoft about 30 years to get to that point.
>> 
>> What may be a larger difference, or may just be my lack of Linux-foo,
>> is this:
>> 
>> PS C:\python33> $script = @"
>> import os
>> for root, dirs, files in os.walk("."):
>>     if len(dirs + files) == 1: print(root)
>> "@
>> 
>> PS C:\python33> python -c $script
>> .\Doc
>> .\Lib\concurrent\__pycache__
>> .\Lib\curses\__pycache__
>> ...
>> 
>> which is a style I've found useful for example when running a group
>> of related timeit.py commands as I can put things like multi-line
>> setup statements in a variable and then have a simpler command to
>> repeat. 
>> 
>> But bash as far as I can won't let me do that:
>> 
>> $ script='import os
>> for root, dirs, files in os.walk("."):
>>     if len(dirs + files) == 1: print(root)
>> '
>> $ python -c $script
>>   File "<string>", line 1
>>     import
>>          ^
>> SyntaxError: invalid syntax
>  
> $ script='import os
>> for root, dirs, files in os.walk("."):
>>     if len(dirs + files) == 1:
>>         print(root)
>> '
> $ python3 -c "$script"
> .
> ./heureka
> 
> $ python3 -c 'import sys; print(sys.argv)' $script
> ['-c', 'import', 'os', 'for', 'root,', 'dirs,', 'files', 'in', 
> 'os.walk("."):', 'if', 'len(dirs', '+', 'files)', '==', '1:',
> 'print(root)'] $ python3 -c 'import sys; print(sys.argv)' "$script"
> ['-c', 'import os\nfor root, dirs, files in os.walk("."):\n    if
> len(dirs + files) == 1:\n        print(root)\n']
> 
Thanks, I thought there must be a way to do that (and I should have 
remembered it). It nicely shows up the difference between the *nix 
shells that are all about processing the command line as a string and 
the Powershell way where it is all about objects (so a single value 
stays as a single argument).

-- 
Duncan Booth

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web