pythonplumbum

Python plumbum: Passing $ in an cmd argument


I am trying to execute the following command in python using plumbum:

sort -u -f -t$'\t' -k1,1 file1 > file2

However, I am having issues passing the -t$'\t' argument. Here is my code:

from plumbum.cmd import sort
separator = r"-t$'\t'"
print separator
cmd = (sort["-u", "-f", separator, "-k1,1", "file1"]) > "file2"
print cmd
print cmd()

I can see problems right away after print separator and print cmd() executes:

-t$'\t'
/usr/bin/sort -u -f "-t\$'\\t'" -k1,1 file1 > file2
  1. The argument is wrapped in double quotes.
  2. An extra \ before $ and \t is inserted.

How should I pass this argument to plumbum?


Solution

  • You may have stumbled into limitations of the command line escaping.

    I could make it work using subprocess module, passing a real tabulation char litteraly:

    import subprocess
    
    p=subprocess.Popen(["sort","-u","-f","-t\t","-k1,1","file1",">","file2"],shell=True)
    p.wait()
    

    Also, full python short solution that does what you want:

    with open("file1") as fr, open("file2","w") as fw:
        fw.writelines(sorted(set(fr),key=lambda x : x.split("\t")[0]))
    

    The full python solution doesn't work exactly the same way sort does when dealing with unicity. If 2 lines have the same first field but not the same second field, sort keeps one of them, whereas the set will keep both.

    EDIT: unchecked but you just confirmed that it works: just tweak your plumbum code with:

    separator = "-t\t"
    

    could just work, although out of the 3 ones, I'd recommend the full python solution since it doesn't involve an external process and therefore is more pythonic and portable.