简体   繁体   English

env: python\r: 没有那个文件或目录

[英]env: python\r: No such file or directory

My Python script beak contains the following shebang:我的 Python 脚本beak包含以下 shebang:

#!/usr/bin/env python

When I run the script $./beak , I get当我运行脚本$./beak时,我得到

env: python\r: No such file or directory

I previously pulled this script from a repository.我之前从存储库中提取了这个脚本。 What could be the reason for this?这可能是什么原因?

Open the file in vim or vi , and administer the following command:vimvi打开文件,并管理以下命令:

:set ff=unix

Save and exit:保存并退出:

:wq

Done!完毕!

Explanation解释

ff stands for file format , and can accept the values of unix ( \\n ), dos ( \\r\\n ) and mac ( \\r ) (only meant to be used on pre-intel macs, on modern macs use unix ) . ff代表文件格式,并且可以接受unix ( \\n )、 dos ( \\r\\n ) 和mac ( \\r ) 的值(仅用于 pre-intel macs,在现代 macs 上使用unix

To read more about the ff command:要阅读有关ff命令的更多信息:

:help ff

:wq stands for W rite and Q uit, a faster equivalent is Shift + zz (ie hold down Shift then press z twice). :wq代表W¯¯仪式和Q UIT,更快的相当于是Shift + ZZ(即按住Shift键,然后按z两次)。

Both commands must be used incommand mode .这两个命令都必须在命令模式下使用

Usage on multiple files对多个文件的使用

It is not necessary to actually open the file in vim.没有必要在 vim 中实际打开文件。 The modification can be made directly from the command line:可以直接从命令行进行修改:

 vi +':wq ++ff=unix' file_with_dos_linebreaks.py

To process multiple *.py files (in bash ):处理多个*.py文件(在bash ):

for file in *.py ; do
    vi +':w ++ff=unix' +':q' "${file}"
done

😱 offtopic : if by chance you are stuck in vim and need to exit, here are some easy ways. 😱 offtopic : 如果你碰巧卡在 vim 中并且需要退出,这里有一些简单的方法。

Removing the BOM mark去除BOM标记

Sometimes even after setting unix line endings you might still get an error running the file, especially if the file is executable and has a shebang .有时即使在设置了 unix 行结束符之后,您仍然可能会在运行文件时遇到错误,特别是如果文件是可执行的并且有shebang The script might have a BOM marker (such as 0xEFBBBF or other) which makes the shebang invalid and causes the shell to complain.该脚本可能有一个 BOM 标记(例如0xEFBBBF或其他),这会使 shebang 无效并导致 shell 抱怨。 In these cases python myscript.py will work fine (since python can handle the BOM) but ./myscript.py will fail even with the execution bit set because your shell (sh, bash, zsh, etc) can't handle the BOM mark.在这些情况下, python myscript.py可以正常工作(因为 python 可以处理 BOM)但是./myscript.py即使设置了执行位也会失败,因为您的 shell(sh、bash、zsh 等)无法处理 BOM标记。 (It's usually windows editors such as Notepad which create files with a BOM mark.) (通常是 Windows 编辑器,例如记事本,它们会创建带有 BOM 标记的文件。)

The BOM can be removed using vim with the following command:可以使用vim使用以下命令删除 BOM:

:set nobomb

The script contains CR characters.该脚本包含 CR 字符。 The shell interprets these CR characters as arguments. Shell 将这些 CR 字符解释为参数。

Solution: Remove the CR characters from the script using the following script.解决方案:使用以下脚本从脚本中删除 CR 字符。

with open('beak', 'rb+') as f:
    content = f.read()
    f.seek(0)
    f.write(content.replace(b'\r', b''))
    f.truncate()

您可以将行结尾转换为 *nix-friendly 的

dos2unix beak

If you use PyCharm you can easily solve it by set the line separator to LF.如果您使用 PyCharm,您可以通过将行分隔符设置为 LF 来轻松解决它。 See my screenshot.看我的截图。 如您所见,您可以将其设置在右下角

The answer of falsetru did absolutely solve my problem. falsetru 的答案确实解决了我的问题。 I wrote a small helper that allows me to normalize line-endings of multiple files.我写了一个小助手,它允许我规范化多个文件的行尾。 As I am not very familar with the line-endings stuff on multiple platforms, etc. the terminology used in the program might not be 100% correct.由于我不太熟悉多个平台上的行尾内容等,程序中使用的术语可能不是 100% 正确。

#!/usr/bin/env python
# Copyright (c) 2013  Niklas Rosenstein
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.

import os
import sys
import glob
import argparse

def process_file(name, lend):
    with open(name, 'rb') as fl:
        data = fl.read()

    data = data.replace('\r\n', '\n').replace('\r', '\n')
    data = data.replace('\n', lend)
    with open(name, 'wb') as fl:
        fl.write(data)

def main():
    parser = argparse.ArgumentParser(description='Convert line-endings of one '
            'or more files.')
    parser.add_argument('-r', '--recursive', action='store_true',
            help='Process all files in a given directory recursively.')
    parser.add_argument('-d', '--dest', default='unix',
            choices=('unix', 'windows'), help='The destination line-ending '
            'type. Default is unix.')
    parser.add_argument('-e', '--is-expr', action='store_true',
            help='Arguments passed for the FILE parameter are treated as '
            'glob expressions.')
    parser.add_argument('-x', '--dont-issue', help='Do not issue missing files.',
            action='store_true')
    parser.add_argument('files', metavar='FILE', nargs='*',
            help='The files or directories to process.')
    args = parser.parse_args()

    # Determine the new line-ending.
    if args.dest == 'unix':
        lend = '\n'
    else:
        lend = '\r\n'

    # Process the files/direcories.
    if not args.is_expr:
        for name in args.files:
            if os.path.isfile(name):
                process_file(name, lend)
            elif os.path.isdir(name) and args.recursive:
                for dirpath, dirnames, files in os.walk(name):
                    for fn in files:
                        fn = os.path.join(dirpath, fn)
                        process_file(fn, fn)
            elif not args.dont_issue:
                parser.error("File '%s' does not exist." % name)
    else:
        if not args.recursive:
            for name in args.files:
                for fn in glob.iglob(name):
                    process_file(fn, lend)
        else:
            for name in args.files:
                for dirpath, dirnames, files in os.walk('.'):
                    for fn in glob.iglob(os.path.join(dirpath, name)):
                        process_file(fn, lend)

if __name__ == "__main__":
    main()

我通过运行 python3 解决了这个错误,即 python3 \\path\\filename.py

预提交钩子解决了我的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM