Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #72267 > unrolled thread
| Started by | Chris Angelico <rosuav@gmail.com> |
|---|---|
| First post | 2014-05-30 10:52 +1000 |
| Last post | 2014-06-01 20:43 +0000 |
| Articles | 15 — 6 participants |
Back to article view | Back to comp.lang.python
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
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-05-30 10:52 +1000 |
| Subject | Multi-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]
| From | Rustom Mody <rustompmody@gmail.com> |
|---|---|
| Date | 2014-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]
| From | Rustom Mody <rustompmody@gmail.com> |
|---|---|
| Date | 2014-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]
| From | Rustom Mody <rustompmody@gmail.com> |
|---|---|
| Date | 2014-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]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2014-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]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2014-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]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-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]
| From | Rustom Mody <rustompmody@gmail.com> |
|---|---|
| Date | 2014-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]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-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]
| From | Duncan Booth <duncan.booth@invalid.invalid> |
|---|---|
| Date | 2014-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]
| From | Devin Jeanpierre <jeanpierreda@gmail.com> |
|---|---|
| Date | 2014-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]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-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]
| From | Duncan Booth <duncan.booth@invalid.invalid> |
|---|---|
| Date | 2014-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]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2014-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]
| From | Duncan Booth <duncan.booth@invalid.invalid> |
|---|---|
| Date | 2014-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