运行shell命令并捕获输出


905

我想编写一个函数,它将执行shell命令并以字符串形式返回其输出,无论它是错误还是成功消息。我只想获得与命令行相同的结果。

能做到这一点的代码示例是什么?

例如:

def run_command(cmd):
    # ??????

print run_command('mysqladmin create test -uroot -pmysqladmin12')
# Should output something like:
# mysqladmin: CREATE DATABASE failed; error: 'Can't create database 'test'; database exists'

Answers:


1137

这个问题的答案取决于您使用的Python版本。最简单的方法是使用以下subprocess.check_output功能:

>>> subprocess.check_output(['ls', '-l'])
b'total 0\n-rw-r--r--  1 memyself  staff  0 Mar 14 11:04 files\n'

check_output运行一个仅接受参数作为输入的程序。1它完全返回打印到的结果stdout。如果您需要将输入内容写入stdin,请跳至runPopen部分。如果要执行复杂的Shell命令,请参阅shell=True此答案末尾的注释。

check_output功能适用于仍在广泛使用的几乎所有版本的Python(2.7+)。2但对于较新的版本,不再推荐使用此方法。

现代版本的Python(3.5或更高版本): run

如果您使用的是Python 3.5或更高版本,并且不需要向后兼容,则建议使用run功能。它为该subprocess模块提供了一个非常通用的高级API 。要捕获程序的输出,请将subprocess.PIPE标志传递给stdout关键字参数。然后访问stdout返回CompletedProcess对象的属性:

>>> import subprocess
>>> result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
>>> result.stdout
b'total 0\n-rw-r--r--  1 memyself  staff  0 Mar 14 11:04 files\n'

返回值是一个bytes对象,因此,如果需要正确的字符串,则需要decode它。假设被调用的进程返回一个UTF-8编码的字符串:

>>> result.stdout.decode('utf-8')
'total 0\n-rw-r--r--  1 memyself  staff  0 Mar 14 11:04 files\n'

所有这些都可以压缩为单线:

>>> subprocess.run(['ls', '-l'], stdout=subprocess.PIPE).stdout.decode('utf-8')
'total 0\n-rw-r--r--  1 memyself  staff  0 Mar 14 11:04 files\n'

如果要将输入传递给流程的stdinbytes请将一个对象传递给input关键字参数:

>>> cmd = ['awk', 'length($0) > 5']
>>> input = 'foo\nfoofoo\n'.encode('utf-8')
>>> result = subprocess.run(cmd, stdout=subprocess.PIPE, input=input)
>>> result.stdout.decode('utf-8')
'foofoo\n'

您可以通过传递stderr=subprocess.PIPE(捕获到result.stderr)或stderr=subprocess.STDOUT(捕获到result.stdout常规输出)来捕获错误。如果不关心安全性,您还可以shell=True按照下面的说明通过传递来运行更复杂的Shell命令。

与旧的处理方式相比,这仅增加了一点复杂性。但是我认为值得这样做:现在,您仅需使用该run功能就可以完成几乎所有需要做的事情。

旧版本的Python(2.7-3.4): check_output

如果您使用的是旧版本的Python,或者需要适度的向后兼容性,则可以使用check_output上面简要介绍的函数。自python 2.7开始提供。

subprocess.check_output(*popenargs, **kwargs)  

它采用与Popen(请参见下文)相同的参数,并返回一个包含程序输出的字符串。该答案的开头有一个更详细的用法示例。在Python 3.5及更高版本中,check_output等效于run使用check=Truestdout=PIPE,仅返回stdout属性。

您可以通过stderr=subprocess.STDOUT确保错误信息包含在返回的输出-但在Python中通过一些版本stderr=subprocess.PIPE,以check_output可引起死锁。如果不关心安全性,您还可以shell=True按照下面的说明通过传递来运行更复杂的Shell命令。

如果您需要通过管道stderr传递输入或将输入传递给流程,check_output则将无法完成任务。Popen在这种情况下,请参见下面的示例。

复杂的应用程序和Python的旧版(2.6及以下版本): Popen

如果需要深入的向后兼容性,或者需要比check_output提供的功能更复杂的功能,则必须直接使用Popen对象,这些对象封装了用于子流程的低级API。

所述Popen构造器接受单个命令没有参数,或列表包含指令作为其第一项,其次是任意数量的参数,每个作为列表一个单独的项目。shlex.split可以帮助将字符串解析为格式正确的列表。Popen对象还接受用于进程IO管理和低级配置的许多不同参数

发送输入和捕获输出communicate几乎总是首选方法。如:

output = subprocess.Popen(["mycmd", "myarg"], 
                          stdout=subprocess.PIPE).communicate()[0]

要么

>>> import subprocess
>>> p = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE, 
...                                    stderr=subprocess.PIPE)
>>> out, err = p.communicate()
>>> print out
.
..
foo

如果设置stdin=PIPEcommunicate还允许您通过以下方式将数据传递到流程stdin

>>> cmd = ['awk', 'length($0) > 5']
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
...                           stderr=subprocess.PIPE,
...                           stdin=subprocess.PIPE)
>>> out, err = p.communicate('foo\nfoofoo\n')
>>> print out
foofoo

艾伦·霍尔的回答,这表明在某些系统上,你可能需要设置stdoutstderr以及stdin所有PIPE(或DEVNULL)得到communicate工作的。

在极少数情况下,您可能需要复杂的实时输出捕获。Vartec的答案提出了一条前进的道路,但是communicate如果不谨慎使用,则其他方法都容易出现死锁。

与上述所有功能一样,当不考虑安全性时,可以通过传递运行更复杂的Shell命令shell=True

笔记

1.运行shell命令:shell=True参数

通常,对runcheck_outputPopen构造函数的每次调用都会执行一个程序。这意味着没有花哨的bash风格的管道。如果要运行复杂的Shell命令,则可以传递shell=True,这三个功能都支持。

但是,这样做会引起安全问题。如果您要做的不仅仅是轻脚本编写,那么最好单独调用每个进程,并将每个进程的输出作为输入通过以下方式传递给下一个进程:

run(cmd, [stdout=etc...], input=other_output)

要么

Popen(cmd, [stdout=etc...]).communicate(other_output)

直接连接管道的诱惑力很强;抵抗它。否则,您很可能会遇到僵局,或者不得不执行类似此类的骇人行为。

2. Unicode注意事项

check_output在Python 2中返回一个字符串,但bytes在Python 3中返回一个对象。如果您还没有花时间学习unicode,那么值得花一点时间。


5
无论与check_output()communicate()你不得不等待,直到这个过程完成,用poll()你得到的输出,因为它涉及。确实取决于您的需求。
vartec

2
不知道这是否仅适用于更高版本的Python,但是该变量对我来说out是类型<class 'bytes'>。为了获得作为字符串的输出,我必须在打印之前将其解码,如下所示:out.decode("utf-8")
PolyMesh 2013年

1
@par当您通过时对您不起作用shell=True?这个对我有用。shlex.split通过时不需要shell=Trueshlex.split适用于非Shell命令。我想我要删除一点,因为这使水变得浑浊。
senderle '17

2
Python 3.5+允许使用关键字参数universal_newlines=True,该参数可让您以系统的默认编码传入和传出Unicode字符串。在3.7中,此名称被重命名为更明智text=True
重奏

2
对于Python 3.6+,您可以使用encoding参数subprocess.run而不是using result.stdout.decode('utf-8'),可以使用subprocess.run(['ls', '-l'], stdout=subprocess.PIPE, encoding='utf-8')
Pierre

191

这很容易,但仅适用于Unix(包括Cygwin)和Python2.7。

import commands
print commands.getstatusoutput('wc -l file')

它返回带有(return_value,output)的元组。

对于适用于Python2和Python3的解决方案,请改用subprocess模块:

from subprocess import Popen, PIPE
output = Popen(["date"],stdout=PIPE)
response = output.communicate()
print response

31
现在已弃用,但对于不带
subprocess.check_output的

22
请注意,这是特定于Unix的。例如,它将在Windows上失败。
Zitrax

4
+1我必须处理python 2.4的古代版本,这非常有帮助
javadba 2014年

1
什么是PIPE dude来显示完整代码:subprocess.PIPE
凯尔·布​​莱恩斯汀

@KyleBridenstine,您可以编辑答案。
鲍里斯(Boris)

106

像这样:

def runProcess(exe):    
    p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    while(True):
        # returns None while subprocess is running
        retcode = p.poll() 
        line = p.stdout.readline()
        yield line
        if retcode is not None:
            break

请注意,我正在将stderr重定向到stdout,它可能并非您想要的,但我也想要错误消息。

此函数逐行产生(通常,您必须等待子进程完成才能获得整体输出)。

对于您的情况,用法是:

for line in runProcess('mysqladmin create test -uroot -pmysqladmin12'.split()):
    print line,

确保实现某种活动循环以获取输出,以避免潜在的死锁waitcall功能。
安德烈·卡隆(

@Silver Light:您的进程可能正在等待用户输入。尝试提供一个PIPE值,stdin并在Popen返回时立即关闭该文件。
安德烈·卡隆(

4
-1:如果retcode是,则为无限循环0。支票应该是if retcode is not None。你不应该产生空字符串(甚至一个空行是至少一个符号“\ n”) if line: yield line。最后致电p.stdout.close()
jfs

2
我用ls -l / dirname尝试了代码,列出了两个文件,但目录中还有更多文件后,它中断了
Vasilis 2013年

3
@fuenfundachtzig:在读取所有输出.readlines()之前不会返回,因此对于无法容纳在内存中的大型输出会中断。另外,为了避免子进程退出后丢失缓冲数据,应该使用if retcode is not None: yield from p.stdout.readlines(); break
jfs

67

Vartec的答案无法读取所有行,因此我制作了一个可以读取的版本:

def run_command(command):
    p = subprocess.Popen(command,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.STDOUT)
    return iter(p.stdout.readline, b'')

用法与接受的答案相同:

command = 'mysqladmin create test -uroot -pmysqladmin12'.split()
for line in run_command(command):
    print(line)

6
您可以使用return iter(p.stdout.readline, b'')而不是while循环
jfs 2012年

2
那是iter的一个很酷的用法,不知道!我更新了代码。
Max Ekman 2012年

我很确定stdout会保留所有输出,这是带有缓冲区的流对象。在Popen完成之后,我使用了一种非常相似的技术来耗尽所有剩余的输出,在我的情况下,在执行过程中还使用poll()和readline来实时捕获输出。
Max Ekman 2012年

我删除了我的误导性评论。我可以确认,p.stdout.readline()即使子进程已经退出(p.poll()不是None),也可能会返回非空的先前缓冲的输出。
jfs

此代码无效。看到这里stackoverflow.com/questions/24340877/...

61

这是一个棘手超级简单的解决方案,可在许多情况下使用:

import os
os.system('sample_cmd > tmp')
print open('tmp', 'r').read()

使用命令的输出创建一个临时文件(这里是tmp),您可以从中读取所需的输出。

注释中的额外说明:如果是一次性作业,则可以删除tmp文件。如果您需要多次执行此操作,则无需删除tmp。

os.remove('tmp')

5
哈克但超级简单+可以在任何地方工作..可以将其结合mktemp以使其在线程情况下工作
Prakash Rajagaopal

2
也许是最快的方法,但最好添加os.remove('tmp')使其成为“无文件”。
XuMuK '17

@XuMuK一次性工作是对的。如果是重复性工作,则可能无需删除
Mehdi Saman Booy

1
不利于并发,不利于可重入的功能,不利于不像启动前那样离开系统(不清理)
2mia 18'July 13''18

1
@ 2mia显然这很简单,原因是有原因的!如果要将文件用作一种共享内存来进行并行读写,这不是一个好选择。但是,为了…… 就像具有命令输出(例如ls或find或...)一样,这是一个不错的选择。顺便说一句,如果您需要一个简单问题的快速解决方案,那是我认为最好的。如果您需要管道,则子流程将为您提高效率。
Mehdi Saman Booy

44

我遇到了同样的问题,但是想出了一种非常简单的方法:

import subprocess
output = subprocess.getoutput("ls -l")
print(output)

希望能帮上忙

注意:此解决方案特定subprocess.getoutput()于Python3,因为在Python2中不起作用


这如何解决OP的问题?请详细说明。
RamenChef

4
它以字符串形式返回命令的输出,就这么简单
azhar22k 2016年

1
当然,print是关于Python 2的声明。您应该能够确定这是Python 3的答案。

2
@Dev print(s)是有效的python2。subprocess.getoutput无效。
user48956 '17

2
对于大多数用例,这是人们可能想要的:易于记忆,不必对结果进行解码等。谢谢。
bwv549

18

您可以使用以下命令来运行任何shell命令。我在ubuntu上使用过它们。

import os
os.popen('your command here').read()

注意:自python 2.6起不推荐使用。现在,您必须使用subprocess.Popen。以下是示例

import subprocess

p = subprocess.Popen("Your command", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
print p.split("\n")


1
@FilippoVitale谢谢。我不知道它已被弃用。
穆罕默德·哈桑

1
根据raspberrypi.stackexchange.com/questions/71547/…,Python os.popen() 2.6 推荐使用,但Python 3.x 推荐使用,因为在3.x中使用来实现subprocess.Popen()
JL

12

您的里程可能会有所不同,我尝试使用@senderle在Windows 2.6.5上的Windows中使用Vartec的解决方案,但我遇到了错误,并且没有其他解决方案起作用。我的错误是:WindowsError: [Error 6] The handle is invalid

我发现必须将PIPE分配给每个句柄才能使其返回我期望的输出-以下内容对我有用。

import subprocess

def run_command(cmd):
    """given shell command, returns communication tuple of stdout and stderr"""
    return subprocess.Popen(cmd, 
                            stdout=subprocess.PIPE, 
                            stderr=subprocess.PIPE, 
                            stdin=subprocess.PIPE).communicate()

并像这样调用([0]获取元组的第一个元素stdout):

run_command('tracert 11.1.0.1')[0]

学习更多之后,我相信我需要这些管道参数,因为我正在使用不同句柄的自定义系统上工作,因此必须直接控制所有std。

要停止控制台弹出窗口(在Windows中),请执行以下操作:

def run_command(cmd):
    """given shell command, returns communication tuple of stdout and stderr"""
    # instantiate a startupinfo obj:
    startupinfo = subprocess.STARTUPINFO()
    # set the use show window flag, might make conditional on being in Windows:
    startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
    # pass as the startupinfo keyword argument:
    return subprocess.Popen(cmd,
                            stdout=subprocess.PIPE, 
                            stderr=subprocess.PIPE, 
                            stdin=subprocess.PIPE, 
                            startupinfo=startupinfo).communicate()

run_command('tracert 11.1.0.1')

1
有趣-这一定是Windows的事情。如果有人遇到类似的错误,我将添加一条注释指向此。
senderle

使用DEVNULL替代subprocess.PIPE,如果你不写从管道/读,否则你可能会挂起的子进程。
jfs 2014年

10

对于以下问题,我对同一问题的口味略有不同:

  1. 当STDOUT消息在STDOUT缓冲区中累积时(即实时)捕获并返回它们。
    • @vartec通过使用生成器和
      上面的'yield' 关键字以Python方式解决了这个问题
  2. 打印所有STDOUT行(即使在可以完全读取STDOUT缓冲区之前退出进程
  3. 不要浪费CPU周期以高频率轮询进程
  4. 检查子流程的返回码
  5. 如果得到非零错误返回码,则打印STDERR(与STDOUT分开)。

我结合并调整了先前的答案,以得出以下结论:

import subprocess
from time import sleep

def run_command(command):
    p = subprocess.Popen(command,
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE,
                         shell=True)
    # Read stdout from subprocess until the buffer is empty !
    for line in iter(p.stdout.readline, b''):
        if line: # Don't print blank lines
            yield line
    # This ensures the process has completed, AND sets the 'returncode' attr
    while p.poll() is None:                                                                                                                                        
        sleep(.1) #Don't waste CPU-cycles
    # Empty STDERR buffer
    err = p.stderr.read()
    if p.returncode != 0:
       # The run_command() function is responsible for logging STDERR 
       print("Error: " + str(err))

此代码将与以前的答案相同地执行:

for line in run_command(cmd):
    print(line)

1
您介意解释增加sleep(.1)不会浪费CPU周期吗?
Moataz Elmasry

2
如果我们p.poll()在两次调用之间没有任何睡眠的情况下继续调用,则通过数百万次调用此函数将浪费CPU周期。取而代之的是,我们通过告诉操作系统在接下来的1/10秒内无需打扰,从而“限制”了循环,以便它可以执行其他任务。(p.poll()也可能会休眠,从而使我们的sleep语句变得多余)。
Aelfinn

5

拆分初始命令 subprocess可能会很棘手且麻烦。

采用 shlex.split()帮助自己。

样例命令

git log -n 5 --since "5 years ago" --until "2 year ago"

编码

from subprocess import check_output
from shlex import split

res = check_output(split('git log -n 5 --since "5 years ago" --until "2 year ago"'))
print(res)
>>> b'commit 7696ab087a163e084d6870bb4e5e4d4198bdc61a\nAuthor: Artur Barseghyan...'

没有shlex.split()代码的话看起来如下

res = check_output([
    'git', 
    'log', 
    '-n', 
    '5', 
    '--since', 
    '5 years ago', 
    '--until', 
    '2 year ago'
])
print(res)
>>> b'commit 7696ab087a163e084d6870bb4e5e4d4198bdc61a\nAuthor: Artur Barseghyan...'

1
shlex.split()这是一种方便,特别是如果您不知道shell中的精确引用如何工作时;但是['git', 'log', '-n', '5', '--since', '5 years ago', '--until', '2 year ago'],如果您理解引用,那么手动将该字符串转换为列表并不困难。
Tripleee

4

如果您需要在多个文件上运行一个shell命令,那么这对我就成功了。

import os
import subprocess

# Define a function for running commands and capturing stdout line by line
# (Modified from Vartec's solution because it wasn't printing all lines)
def runProcess(exe):    
    p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    return iter(p.stdout.readline, b'')

# Get all filenames in working directory
for filename in os.listdir('./'):
    # This command will be run on each file
    cmd = 'nm ' + filename

    # Run the command and capture the output line by line.
    for line in runProcess(cmd.split()):
        # Eliminate leading and trailing whitespace
        line.strip()
        # Split the output 
        output = line.split()

        # Filter the output and print relevant lines
        if len(output) > 2:
            if ((output[2] == 'set_program_name')):
                print filename
                print line

编辑:刚刚看到了JF Sebastian的建议的Max Persson的解决方案。继续前进,并纳入。


Popen接受一个字符串,但是需要shell=True,或者一个参数列表,在这种情况下,您应该传入['nm', filename]而不是字符串。后者是可取的,因为外壳会增加复杂性,而在此处不提供任何价值。传递一个没有shell=True明显传递字符串的操作显然在Windows上可行,但是在任何下一版本的Python中都可能会改变。
Tripleee

2

根据@senderle,如果您像我一样使用python3.6:

def sh(cmd, input=""):
    rst = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, input=input.encode("utf-8"))
    assert rst.returncode == 0, rst.stderr.decode("utf-8")
    return rst.stdout.decode("utf-8")
sh("ls -a")

就像您在bash中运行命令一样


您正在重塑关键字arguments check=True, universal_newlines=True。换句话说subprocess.run(),您的代码已经完成了所有工作。
点钟

1

如果您使用 subprocess python模块,则可以分别处理STDOUT,STDERR和命令的返回代码。您可以看到完整的命令调用程序实现的示例。当然,您可以根据需要扩展它try..except

下面的函数返回STDOUT,STDERR和Return代码,因此您可以在其他脚本中处理它们。

import subprocess

def command_caller(command=None)
    sp = subprocess.Popen(command, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=False)
    out, err = sp.communicate()
    if sp.returncode:
        print(
            "Return code: %(ret_code)s Error message: %(err_msg)s"
            % {"ret_code": sp.returncode, "err_msg": err}
            )
    return sp.returncode, out, err

另一个糟糕的重新实现subprocess.run()。不要重新发明轮子。
Tripleee

0

例如,execute('ls -ahl')区分了三种/四种可能的收益和OS平台:

  1. 无输出,但运行成功
  2. 输出空行,运行成功
  3. 运行失败
  4. 输出一些东西,成功运行

功能如下

def execute(cmd, output=True, DEBUG_MODE=False):
"""Executes a bash command.
(cmd, output=True)
output: whether print shell output to screen, only affects screen display, does not affect returned values
return: ...regardless of output=True/False...
        returns shell output as a list with each elment is a line of string (whitespace stripped both sides) from output
        could be 
        [], ie, len()=0 --> no output;    
        [''] --> output empty line;     
        None --> error occured, see below

        if error ocurs, returns None (ie, is None), print out the error message to screen
"""
if not DEBUG_MODE:
    print "Command: " + cmd

    # https://stackoverflow.com/a/40139101/2292993
    def _execute_cmd(cmd):
        if os.name == 'nt' or platform.system() == 'Windows':
            # set stdin, out, err all to PIPE to get results (other than None) after run the Popen() instance
            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        else:
            # Use bash; the default is sh
            p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, executable="/bin/bash")

        # the Popen() instance starts running once instantiated (??)
        # additionally, communicate(), or poll() and wait process to terminate
        # communicate() accepts optional input as stdin to the pipe (requires setting stdin=subprocess.PIPE above), return out, err as tuple
        # if communicate(), the results are buffered in memory

        # Read stdout from subprocess until the buffer is empty !
        # if error occurs, the stdout is '', which means the below loop is essentially skipped
        # A prefix of 'b' or 'B' is ignored in Python 2; 
        # it indicates that the literal should become a bytes literal in Python 3 
        # (e.g. when code is automatically converted with 2to3).
        # return iter(p.stdout.readline, b'')
        for line in iter(p.stdout.readline, b''):
            # # Windows has \r\n, Unix has \n, Old mac has \r
            # if line not in ['','\n','\r','\r\n']: # Don't print blank lines
                yield line
        while p.poll() is None:                                                                                                                                        
            sleep(.1) #Don't waste CPU-cycles
        # Empty STDERR buffer
        err = p.stderr.read()
        if p.returncode != 0:
            # responsible for logging STDERR 
            print("Error: " + str(err))
            yield None

    out = []
    for line in _execute_cmd(cmd):
        # error did not occur earlier
        if line is not None:
            # trailing comma to avoid a newline (by print itself) being printed
            if output: print line,
            out.append(line.strip())
        else:
            # error occured earlier
            out = None
    return out
else:
    print "Simulation! The command is " + cmd
    print ""

0

可以将输出重定向到文本文件,然后将其读回。

import subprocess
import os
import tempfile

def execute_to_file(command):
    """
    This function execute the command
    and pass its output to a tempfile then read it back
    It is usefull for process that deploy child process
    """
    temp_file = tempfile.NamedTemporaryFile(delete=False)
    temp_file.close()
    path = temp_file.name
    command = command + " > " + path
    proc = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
    if proc.stderr:
        # if command failed return
        os.unlink(path)
        return
    with open(path, 'r') as f:
        data = f.read()
    os.unlink(path)
    return data

if __name__ == "__main__":
    path = "Somepath"
    command = 'ecls.exe /files ' + path
    print(execute(command))

当然可以,但是为什么要这么做?为什么要使用shell而不是传递stdout=temp_file
重奏

实际上,通常来说您是对的,但是在我的示例中,ecls.exe似乎部署了另一个命令行工具,因此有时这种简单的方法行不通。
MR

0

刚刚写了一个小的bash脚本来使用curl做到这一点

https://gist.github.com/harish2704/bfb8abece94893c53ce344548ead8ba5

#!/usr/bin/env bash

# Usage: gdrive_dl.sh <url>

urlBase='https://drive.google.com'
fCookie=tmpcookies

curl="curl -L -b $fCookie -c $fCookie"
confirm(){
    $curl "$1" | grep jfk-button-action | sed -e 's/.*jfk-button-action" href="\(\S*\)".*/\1/' -e 's/\&amp;/\&/g'
}

$curl -O -J "${urlBase}$(confirm $1)"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.