`echo %!(*`

Discussion in 'Ruby' started by Tom Felker, Aug 31, 2003.

  1. Tom Felker

    Tom Felker Guest

    Hello all,

    Does anyone know a way to do backtick interpolation while protecting the
    command's arguments from the shell, or bypassing the shell entirely? I'm
    writing a script to rename badly named music files, and I have to pass the
    bad name to vorbiscomment and read it's output.

    Apparently Kernel::` is a method, but I can't figure out how to call it
    with my own arguments. Is there a non-punctuation name for it? This
    would only be useful if it could accept an argument list as an array and
    not use the shell, as Kernel::system does.

    Thanks,
    --
    Tom Felker, <>
    <http://vlevel.sourceforge.net> - Stop fiddling with the volume knob.

    I'm not comfortable with an idea that's not constantly being challenged.
     
    Tom Felker, Aug 31, 2003
    #1
    1. Advertising

  2. I'm not sure I understand what you're asking about backtick
    interpolation. Can you give me a simple example of what you'd like the
    backtick to do so I understand beter?

    As for renaming a file, would File.rename do what you want? :

    dcarrera ~ $ ls *.mp3
    BadlyNamedFile.mp3
    dcarrera ~ $ ruby -e 'File.rename("BadlyNamedFile.mp3", "NewName.mp3")'
    dcarrera ~ $ ls *.mp3
    NewName.mp3


    On Mon, Sep 01, 2003 at 07:46:24AM +0900, Tom Felker wrote:
    > Hello all,
    >
    > Does anyone know a way to do backtick interpolation while protecting the
    > command's arguments from the shell, or bypassing the shell entirely? I'm
    > writing a script to rename badly named music files, and I have to pass the
    > bad name to vorbiscomment and read it's output.
    >
    > Apparently Kernel::` is a method, but I can't figure out how to call it
    > with my own arguments. Is there a non-punctuation name for it? This
    > would only be useful if it could accept an argument list as an array and
    > not use the shell, as Kernel::system does.
    >
    > Thanks,
    > --
    > Tom Felker, <>
    > <http://vlevel.sourceforge.net> - Stop fiddling with the volume knob.
    >
    > I'm not comfortable with an idea that's not constantly being challenged.
    >


    --
    Daniel Carrera, Math PhD student at UMD. PGP KeyID: 9AF77A88
    .-"~~~"-.
    / O O \ ATTENTION ALL PASCAL USERS:
    : s :
    \ \___/ / To commemorate the anniversary of Blaise Pascal's
    `-.___.-' birth (today) all your programs will run at half speed.
     
    Daniel Carrera, Aug 31, 2003
    #2
    1. Advertising

  3. "Tom Felker" <> wrote in message
    > Does anyone know a way to do backtick interpolation while protecting the
    > command's arguments from the shell, or bypassing the shell entirely?


    I am not sure that I understand what you mean by "bypassing the shell",
    but will this work for you:

    a="%!(*"
    %x{echo #{a}}

    > writing a script to rename badly named music files, and I have to pass the
    > bad name to vorbiscomment and read it's output.


    What is a "vorbiscomment" ?

    > Apparently Kernel::` is a method, but I can't figure out how to call it
    > with my own arguments. Is there a non-punctuation name for it? This


    Again, I do not understand this "call with my own arguments" part. Is this
    some *ix lingo ? Pardon my ignorance.

    > would only be useful if it could accept an argument list as an array and
    > not use the shell, as Kernel::system does.


    At least on Windows, both system and backtick use the shell...I think ;)

    > Thanks,
    > --
    > Tom Felker, <>


    HTH,
    -- shanko
     
    Shashank Date, Sep 1, 2003
    #3
  4. Tom Felker

    Tom Felker Guest

    On Mon, 01 Sep 2003 07:51:55 +0900, Daniel Carrera wrote:

    > I'm not sure I understand what you're asking about backtick
    > interpolation. Can you give me a simple example of what you'd like the
    > backtick to do so I understand beter?


    oldName = "02_Ship_At_Sea_(Instrumental).ogg"
    tags = Hash.new
    `vorbiscomment #{oldName}`.each_line do |line|
    key, value = line.split("=", 2)
    tags[key.downcase] = value
    end
    # ...use tags to formulate proper filename and rename

    # Errors:
    sh: -c: line 1: syntax error near unexpected token `('
    sh: -c: line 1: `vorbiscomment 02_Ship_At_Sea_(Instrumental).ogg'
    ....

    If you use system, you can pass the arguments in an array, and the shell
    isn't used, so you can have arguments that the shell would barf on.

    system("echo !@#$%^&") == ""
    system("echo", "!@#$%^&") == "!@#$%^&")

    I need a backtick method that works the same way. Having popen work
    that way would be nice. As it is, I think it's only possible with
    popen("-"), having the child exec in such a way as to not interpolate
    the arguments, and reading from that.

    --
    Tom Felker, <>
    <http://vlevel.sourceforge.net> - Stop fiddling with the volume knob.

    ruby -r complex -e 'c,m,w,h=Complex(-0.75,0.136),50,150,100;puts"P6\n#{w}\n#{h}\
    n255";(0...h).each{|j|(0...w).each{|i|n,z=0,Complex(.9*i/w,.9*j/h);while n<=m&&(
    z-c).abs<=2;z=z*z+c;n+=1 end;print [10+n*15,0,rand*99].pack("C*")}}'|display
    #by Michael Neumann AFAICT
     
    Tom Felker, Sep 1, 2003
    #4
  5. Try this:

    - `vorbiscomment #{oldName}`.each_line do |line|
    + `vorbiscomment "#{oldName}"`.each_line do |line|

    The quotes should make the shell interpret the name literally, instead of
    seeing the brackets as a token.

    Cheers,
    Daniel.

    On Mon, Sep 01, 2003 at 08:46:33AM +0900, Tom Felker wrote:
    > On Mon, 01 Sep 2003 07:51:55 +0900, Daniel Carrera wrote:
    >
    > > I'm not sure I understand what you're asking about backtick
    > > interpolation. Can you give me a simple example of what you'd like the
    > > backtick to do so I understand beter?

    >
    > oldName = "02_Ship_At_Sea_(Instrumental).ogg"
    > tags = Hash.new
    > `vorbiscomment #{oldName}`.each_line do |line|
    > key, value = line.split("=", 2)
    > tags[key.downcase] = value
    > end
    > # ...use tags to formulate proper filename and rename
    >
    > # Errors:
    > sh: -c: line 1: syntax error near unexpected token `('
    > sh: -c: line 1: `vorbiscomment 02_Ship_At_Sea_(Instrumental).ogg'
    > ....
    >
    > If you use system, you can pass the arguments in an array, and the shell
    > isn't used, so you can have arguments that the shell would barf on.
    >
    > system("echo !@#$%^&") == ""
    > system("echo", "!@#$%^&") == "!@#$%^&")
    >
    > I need a backtick method that works the same way. Having popen work
    > that way would be nice. As it is, I think it's only possible with
    > popen("-"), having the child exec in such a way as to not interpolate
    > the arguments, and reading from that.
    >
    > --
    > Tom Felker, <>
    > <http://vlevel.sourceforge.net> - Stop fiddling with the volume knob.
    >
    > ruby -r complex -e 'c,m,w,h=Complex(-0.75,0.136),50,150,100;puts"P6\n#{w}\n#{h}\
    > n255";(0...h).each{|j|(0...w).each{|i|n,z=0,Complex(.9*i/w,.9*j/h);while n<=m&&(
    > z-c).abs<=2;z=z*z+c;n+=1 end;print [10+n*15,0,rand*99].pack("C*")}}'|display
    > #by Michael Neumann AFAICT
    >


    --
    Daniel Carrera, Math PhD student at UMD. PGP KeyID: 9AF77A88
    .-"~~~"-.
    / O O \ ATTENTION ALL PASCAL USERS:
    : s :
    \ \___/ / To commemorate the anniversary of Blaise Pascal's
    `-.___.-' birth (today) all your programs will run at half speed.
     
    Daniel Carrera, Sep 1, 2003
    #5
  6. Tom Felker

    Tom Felker Guest

    On Mon, 01 Sep 2003 00:21:11 +0000, Mark J. Reed wrote:

    > On Sun, Aug 31, 2003 at 06:00:34PM -0500, Shashank Date wrote:
    >> I am not sure that I understand what you mean by "bypassing the shell",

    >
    > It's simple. When you execute `some command` (or the equivalent
    > using %x), what Ruby actually executes is your command interpreter
    > ("shell" in Unix-speak), passing it the string between `...`
    > to execute. It's up to the shell to split up the command into
    > words, handle wildcard expansion (at least on UNIX; the command
    > interpreter on Windows leaves that latter duty up to the individual
    > commands), etc. The problem is that all this power is a security
    > hole because it's easy to trick command interpreters into doing
    > ugly things just by passing something nefarious as a "filename".
    >
    > The original poster mentioned Kernel.system, which is the way to
    > execute a command when you don't care about its output.
    > If you pass it one long string, Kernel.system will also invoke the
    > shell, but if instead you pass it separate arguments for each word of
    > the command line, it bypasses the shell and executes the command
    > directly. Thus:
    >
    > system("ps -fp#{$$}") # also invokes the shell
    > system('ps', "-fp#{$$}") # doesn't invoke the shell
    > psOutput = `ps -fp#{$$}` # invokes the shell
    >
    > The question is: how do you complete the list, that is, capture the
    > command output without involving the shell?
    >
    > The only solution of which I'm aware is to use popen/exec:
    >
    > if fd = IO.popen('-') then
    > psOutput = fd.readlines.join("\n")
    > else
    > exec 'ps', "-fp#{$$}"
    > end
    >
    > Of course, you could turn this into a method:
    >
    > def safeBackticks(*args)
    > if fd = IO.popen('-') then
    > output = fd.readlines.join("\n")


    fd.close #right?

    > else
    > exec *args
    > end
    > return output
    > end


    Thanks, that method is exactly what I'm looking for.

    I only wonder why it isn't in Ruby already. Although I personally
    couldn't care less, the above can only be done in Windows by calling
    CreateProcess() directly. Using quotes only works if the filename doesn't
    contain quotes. Escaping it would work, but it's a hack, and dependent on
    the shell. (Windows's cmd will expand %VAR%, IIRC.) It's also kind of
    weird to have a method whose only name is "`".

    ri doesn't say what popen("-") does with no block, though I see
    it returns twice like fork(). Sweet.

    Have fun,
    --
    Tom Felker, <>
    <http://vlevel.sourceforge.net> - Stop fiddling with the volume knob.

    The ability to monopolize a market is insignificant next to the power of the
    source.
     
    Tom Felker, Sep 1, 2003
    #6
  7. On Mon, Sep 01, 2003 at 07:46:24AM +0900, Tom Felker wrote:
    > Apparently Kernel::` is a method, but I can't figure out how to call it
    > with my own arguments. Is there a non-punctuation name for it?


    You can call it explicitly like this:

    Kernel.send:)`, "ls /etc")

    However unlike system, backtick doesn't let you pass a line already broken
    into arguments:

    Kernel.send:)`, "ls", "/etc")
    #>> ArgumentError: wrong number of arguments(2 for 1)

    so that doesn't help you.

    Regards,

    Brian.
     
    Brian Candler, Sep 1, 2003
    #7
  8. On Mon, 1 Sep 2003 10:28:40 +0900
    Wesley J Landaker <> wrote:

    > On Sunday 31 August 2003 6:26 pm, Mark J. Reed wrote:
    > > On Sun, Aug 31, 2003 at 06:00:34PM -0500, Shashank Date wrote:
    > > > I am not sure that I understand what you mean by "bypassing the
    > > > shell",

    >
    > > The only solution of which I'm aware is to use popen/exec:
    > >
    > > if fd = IO.popen('-') then
    > > psOutput = fd.readlines.join("\n")
    > > else
    > > exec 'ps', "-fp#{$$}"
    > > end

    >
    > I believe open3 will do what you want as well:


    Yep, open3 will do it for him. It'd be nice if the "stock" popen would
    support multiple arg to avoid the shell doing the splitting.

    > require 'open3'
    > Open3.popen3("cmd","args","go","here","etc") { |in,out,err|

    ^^
    Syntax error here

    'in' is a Ruby keyword (I think for the 'for x in y' construct.)

    But other than that, the example should work.

    Jason Creighton
     
    Jason Creighton, Sep 2, 2003
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Leszek Dubiel
    Replies:
    3
    Views:
    9,871
  2. Guest

    echo user input

    Guest, May 26, 2005, in forum: ASP .Net
    Replies:
    3
    Views:
    480
    William F. Robertson, Jr.
    May 27, 2005
  3. =?Utf-8?B?Q3JhaWc=?=

    echo for a session variable

    =?Utf-8?B?Q3JhaWc=?=, Aug 16, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    361
  4. Josef Garvi

    Re: echo servers

    Josef Garvi, Aug 3, 2003, in forum: Java
    Replies:
    0
    Views:
    410
    Josef Garvi
    Aug 3, 2003
  5. Jack9

    Echo Server Using NIO

    Jack9, Sep 9, 2003, in forum: Java
    Replies:
    1
    Views:
    2,319
Loading...

Share This Page