Skip to content

Instantly share code, notes, and snippets.

@nanpingxiang
Forked from jonlabelle/crlf.py
Created December 24, 2020 05:24
Show Gist options
  • Save nanpingxiang/c6d8fcbc669f70d3a3d059a8340bfe6b to your computer and use it in GitHub Desktop.
Save nanpingxiang/c6d8fcbc669f70d3a3d059a8340bfe6b to your computer and use it in GitHub Desktop.

Revisions

  1. @jonlabelle jonlabelle revised this gist Oct 7, 2018. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion crlf.py
    Original file line number Diff line number Diff line change
    @@ -161,7 +161,7 @@ def main():
    sys.exit(2)

    if args.dryrun is True and args.quiet is False:
    print('Dry run only... files will not be modifed.')
    print('Dry run only... files will NOT be modifed.')

    for file_to_process in files_to_process:
    if os.path.isdir(file_to_process):
  2. @jonlabelle jonlabelle revised this gist Oct 7, 2018. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions crlf.py
    Original file line number Diff line number Diff line change
    @@ -59,8 +59,7 @@ def _create_temp_file(contents):
    :param contents: The temp file contents.
    :return: The absolute path of the created temp file.
    """
    tf = tempfile.NamedTemporaryFile(
    mode='wb', suffix='txt', delete=False)
    tf = tempfile.NamedTemporaryFile(mode='wb', suffix='txt', delete=False)
    tf.write(contents)
    tf.close()
    return tf.name
    @@ -145,12 +144,14 @@ def main():
    sys.exit(2)

    args = parser.parse_args()

    if args.windows is True and args.unix is True:
    sys.stderr.write("Ambiguous options specified, 'unix' and 'windows'. "
    "Please choose one option, or the other.\n")
    sys.exit(2)

    files_to_process = []

    for argfile in args.files:
    files_to_process.extend(glob.glob(argfile))

  3. @jonlabelle jonlabelle revised this gist Oct 7, 2018. 1 changed file with 59 additions and 62 deletions.
    121 changes: 59 additions & 62 deletions crlf.py
    Original file line number Diff line number Diff line change
    @@ -5,16 +5,15 @@
    from __future__ import print_function

    import argparse
    import glob
    import os
    import sys
    import glob
    import tempfile

    from stat import ST_ATIME, ST_MTIME

    EOL_UNIX = '\n'
    EOL_WINDOWS = '\r\n'
    EOL_MAC = '\r'
    UNIX_NEWLINE = '\n'
    WINDOWS_NEWLINE = '\r\n'
    MAC_NEWLINE = '\r'


    def _normalize_line_endings(lines, line_ending='unix'):
    @@ -25,11 +24,11 @@ def _normalize_line_endings(lines, line_ending='unix'):
    Acceptable values are 'unix' (default), 'windows' and 'mac'.
    :return: Line endings normalized.
    """
    lines = lines.replace(EOL_WINDOWS, EOL_UNIX).replace(EOL_MAC, EOL_UNIX)
    lines = lines.replace(WINDOWS_NEWLINE, UNIX_NEWLINE).replace(MAC_NEWLINE, UNIX_NEWLINE)
    if line_ending == 'windows':
    lines = lines.replace(EOL_UNIX, EOL_WINDOWS)
    lines = lines.replace(UNIX_NEWLINE, WINDOWS_NEWLINE)
    elif line_ending == 'mac':
    lines = lines.replace(EOL_UNIX, EOL_MAC)
    lines = lines.replace(UNIX_NEWLINE, MAC_NEWLINE)
    return lines


    @@ -101,46 +100,54 @@ def main():
    """Main."""
    parser = argparse.ArgumentParser(
    prog='crlf',
    description='Replace CRLF (windows) line endings with LF (unix) line '
    'endings in files (and vice-versa.')
    parser.add_argument('-q', '--quiet',
    help='surpress descriptive messages from output',
    action='store_true',
    default=False)
    parser.add_argument('-n', '--dryrun',
    help='show changes, but do not modify files',
    action='store_true',
    default=False)
    parser.add_argument('-w', '--windows',
    help='replace LF (unix) line endings with '
    'CRLF (windows) line endings',
    action='store_true',
    default=False)
    parser.add_argument('-u', '--unix',
    help='replace CRLF (windows) line endings with '
    'LF (unix) line endings (default)',
    action='store_true',
    default=False)
    parser.add_argument('-t', '--timestamps',
    help="maintains the modfified file's time stamps "
    "(atime and mtime)",
    action='store_true',
    default=False)
    parser.add_argument('files',
    nargs='+',
    help="a list of files or file glob patterns "
    "to process",
    default='.')
    description='Replace CRLF (windows) line endings with LF (unix) '
    'line endings in files (and vice-versa.')

    parser.add_argument(
    '-q', '--quiet',
    help='surpress descriptive messages from output',
    action='store_true',
    default=False)

    parser.add_argument(
    '-n', '--dryrun',
    help='show changes, but do not modify files',
    action='store_true',
    default=False)

    parser.add_argument(
    '-w', '--windows',
    help='replace LF (unix) line endings with CRLF (windows) line endings',
    action='store_true',
    default=False)

    parser.add_argument(
    '-u', '--unix',
    help='replace CRLF (windows) line endings with LF (unix) '
    'line endings (default)',
    action='store_true',
    default=False)

    parser.add_argument(
    '-t', '--timestamps',
    help="maintains the modfified file's time stamps (atime and mtime)",
    action='store_true',
    default=False)

    parser.add_argument(
    'files',
    nargs='+',
    help="a list of files or file glob patterns to process",
    default='.')

    if len(sys.argv) < 2:
    parser.print_help()
    sys.exit(2)

    args = parser.parse_args()

    if args.windows is True and args.unix is True:
    sys.stderr.write("Ambiguous options specified, 'unix' and 'windows'. "
    "Please choose one option or the other.\n")
    "Please choose one option, or the other.\n")
    sys.exit(2)

    files_to_process = []
    @@ -158,16 +165,14 @@ def main():
    for file_to_process in files_to_process:
    if os.path.isdir(file_to_process):
    if args.quiet is False:
    print("- '{0}' : is a directory (skip)"
    .format(file_to_process))
    print("- '{0}' : is a directory (skip)".format(file_to_process))
    continue

    if os.path.isfile(file_to_process):
    data = _read_file_data(file_to_process)
    if '\0' in data:
    if '\\0' in data:
    if args.quiet is False:
    print("- '{0}' : is a binary file (skip)".format(
    file_to_process))
    print("- '{0}' : is a binary file (skip)".format(file_to_process))
    continue

    if args.windows is True:
    @@ -179,19 +184,16 @@ def main():
    if args.quiet is False:
    if args.windows is True:
    if args.dryrun is True:
    print("+ '{0}' : LF would be replaced with CRLF"
    .format(file_to_process))
    print("+ '{0}' : LF would be replaced with CRLF".format(file_to_process))
    else:
    print("+ '{0}' : replacing LF with CRLF"
    .format(file_to_process))
    print("+ '{0}' : replacing LF with CRLF".format(file_to_process))
    else:
    if args.dryrun is True:
    print("+ '{0}' : CRLF would be replaced with LF"
    .format(file_to_process))
    print("+ '{0}' : CRLF would be replaced with LF".format(file_to_process))
    else:
    print("+ '{0}' : replacing CRLF with LF"
    .format(file_to_process))
    print("+ '{0}' : replacing CRLF with LF".format(file_to_process))

    tmp_file_path = ""
    if args.dryrun is False:
    try:
    if args.timestamps is True:
    @@ -200,8 +202,7 @@ def main():
    tmp_file_path = _create_temp_file(data)
    _copy_file_time(file_to_process, tmp_file_path)

    # overwrite the current file with the modfified
    # contents
    # overwrite the current file with the modfified contents
    _write_file_data(file_to_process, newdata)

    if args.timestamps is True:
    @@ -216,15 +217,11 @@ def main():
    else:
    if args.quiet is False:
    if args.windows is True:
    print("- '{0}' : line endings are already CRLF "
    "(windows)"
    .format(file_to_process))
    print("- '{0}' : line endings are already CRLF (windows)".format(file_to_process))
    else:
    print("- '{0}' : line endings are already LF (unix)"
    .format(file_to_process))
    print("- '{0}' : line endings are already LF (unix)".format(file_to_process))
    else:
    sys.stderr.write("- '{0}' : file not found\n"
    .format(file_to_process))
    sys.stderr.write("- '{0}' : file not found\n".format(file_to_process))
    sys.exit(1)


  4. @jonlabelle jonlabelle revised this gist Mar 26, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion crlf.py
    Original file line number Diff line number Diff line change
    @@ -102,7 +102,7 @@ def main():
    parser = argparse.ArgumentParser(
    prog='crlf',
    description='Replace CRLF (windows) line endings with LF (unix) line '
    'endings in files.')
    'endings in files (and vice-versa.')
    parser.add_argument('-q', '--quiet',
    help='surpress descriptive messages from output',
    action='store_true',
  5. @jonlabelle jonlabelle revised this gist Mar 21, 2017. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions crlf.py
    Original file line number Diff line number Diff line change
    @@ -86,8 +86,8 @@ def _read_file_data(filepath):
    return data


    def _write_data_to_file(filepath, data):
    """Write data to file.
    def _write_file_data(filepath, data):
    """Write file data.
    :param filepath: The file path.
    :param data: The data to write.
    @@ -202,7 +202,7 @@ def main():

    # overwrite the current file with the modfified
    # contents
    _write_data_to_file(file_to_process, newdata)
    _write_file_data(file_to_process, newdata)

    if args.timestamps is True:
    # copy the original file's atime and mtime back to
  6. @jonlabelle jonlabelle revised this gist Mar 21, 2017. 1 changed file with 35 additions and 14 deletions.
    49 changes: 35 additions & 14 deletions crlf.py
    Original file line number Diff line number Diff line change
    @@ -70,12 +70,22 @@ def _create_temp_file(contents):
    def _delete_file_if_exists(filepath):
    """Delete the file if it exists.
    :param filepath: The path of the file to delete.
    :param filepath: The file path.
    """
    if os.path.exists(filepath):
    os.remove(filepath)


    def _read_file_data(filepath):
    """Read file data.
    :param filepath: The file path.
    :return: The file contents.
    """
    data = open(filepath, 'rb').read()
    return data


    def _write_data_to_file(filepath, data):
    """Write data to file.
    @@ -101,11 +111,16 @@ def main():
    help='show changes, but do not modify files',
    action='store_true',
    default=False)
    parser.add_argument('-uw', '--unix2windows',
    help='Replace LF (unix) line endings with '
    parser.add_argument('-w', '--windows',
    help='replace LF (unix) line endings with '
    'CRLF (windows) line endings',
    action='store_true',
    default=False)
    parser.add_argument('-u', '--unix',
    help='replace CRLF (windows) line endings with '
    'LF (unix) line endings (default)',
    action='store_true',
    default=False)
    parser.add_argument('-t', '--timestamps',
    help="maintains the modfified file's time stamps "
    "(atime and mtime)",
    @@ -123,41 +138,46 @@ def main():

    args = parser.parse_args()

    if args.windows is True and args.unix is True:
    sys.stderr.write("Ambiguous options specified, 'unix' and 'windows'. "
    "Please choose one option or the other.\n")
    sys.exit(2)

    files_to_process = []
    for argfile in args.files:
    files_to_process.extend(glob.glob(argfile))

    if len(files_to_process) <= 0:
    if args.quiet is False:
    print('No files matched the specified pattern.')
    sys.exit(0)
    sys.stderr.write('No files matched the specified pattern.\n')
    sys.exit(2)

    if args.dryrun is True:
    if args.dryrun is True and args.quiet is False:
    print('Dry run only... files will not be modifed.')

    for file_to_process in files_to_process:
    if os.path.isdir(file_to_process):
    if args.quiet is False:
    print("- '{0}' : directory... skipped"
    print("- '{0}' : is a directory (skip)"
    .format(file_to_process))
    continue

    if os.path.isfile(file_to_process):
    data = open(file_to_process, 'rb').read()
    data = _read_file_data(file_to_process)
    if '\0' in data:
    if args.quiet is False:
    print("- '{0}' : binary file... skipped".format(
    print("- '{0}' : is a binary file (skip)".format(
    file_to_process))
    continue

    if args.unix2windows is True:
    if args.windows is True:
    newdata = _normalize_line_endings(data, line_ending='windows')
    else:
    newdata = _normalize_line_endings(data, line_ending='unix')

    if newdata != data:
    if args.quiet is False:
    if args.unix2windows is True:
    if args.windows is True:
    if args.dryrun is True:
    print("+ '{0}' : LF would be replaced with CRLF"
    .format(file_to_process))
    @@ -191,19 +211,20 @@ def main():
    _copy_file_time(tmp_file_path, file_to_process)
    _delete_file_if_exists(tmp_file_path)
    except Exception as ex:
    print('error : {0}'.format(str(ex)))
    sys.stderr.write('error : {0}\n'.format(str(ex)))
    sys.exit(1)
    else:
    if args.quiet is False:
    if args.unix2windows is True:
    if args.windows is True:
    print("- '{0}' : line endings are already CRLF "
    "(windows)"
    .format(file_to_process))
    else:
    print("- '{0}' : line endings are already LF (unix)"
    .format(file_to_process))
    else:
    print("- '{0}' : file not found".format(file_to_process))
    sys.stderr.write("- '{0}' : file not found\n"
    .format(file_to_process))
    sys.exit(1)


  7. @jonlabelle jonlabelle revised this gist Mar 21, 2017. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion crlf.py
    Original file line number Diff line number Diff line change
    @@ -113,7 +113,8 @@ def main():
    default=False)
    parser.add_argument('files',
    nargs='+',
    help="a list of files, or file patterns to process",
    help="a list of files or file glob patterns "
    "to process",
    default='.')

    if len(sys.argv) < 2:
  8. @jonlabelle jonlabelle revised this gist Mar 21, 2017. 1 changed file with 2 additions and 4 deletions.
    6 changes: 2 additions & 4 deletions crlf.py
    Original file line number Diff line number Diff line change
    @@ -111,11 +111,9 @@ def main():
    "(atime and mtime)",
    action='store_true',
    default=False)
    parser.add_argument('file',
    parser.add_argument('files',
    nargs='+',
    help="a list of files, or file patterns to process. "
    "if no arguments are specified, the current "
    "directory '.' is used",
    help="a list of files, or file patterns to process",
    default='.')

    if len(sys.argv) < 2:
  9. @jonlabelle jonlabelle revised this gist Mar 21, 2017. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion crlf.py
    Original file line number Diff line number Diff line change
    @@ -113,7 +113,6 @@ def main():
    default=False)
    parser.add_argument('file',
    nargs='+',
    # metavar='<files>|<pattern>',
    help="a list of files, or file patterns to process. "
    "if no arguments are specified, the current "
    "directory '.' is used",
  10. @jonlabelle jonlabelle revised this gist Mar 21, 2017. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions crlf.py
    Original file line number Diff line number Diff line change
    @@ -111,9 +111,9 @@ def main():
    "(atime and mtime)",
    action='store_true',
    default=False)
    parser.add_argument('files',
    parser.add_argument('file',
    nargs='+',
    metavar='<files>|<pattern>',
    # metavar='<files>|<pattern>',
    help="a list of files, or file patterns to process. "
    "if no arguments are specified, the current "
    "directory '.' is used",
  11. @jonlabelle jonlabelle revised this gist Mar 21, 2017. 1 changed file with 82 additions and 4 deletions.
    86 changes: 82 additions & 4 deletions crlf.py
    Original file line number Diff line number Diff line change
    @@ -1,19 +1,24 @@
    #!/usr/bin/env python

    """Replace line breaks, from one format to another."""

    from __future__ import print_function

    import argparse
    import os
    import sys
    import glob
    import tempfile

    from stat import ST_ATIME, ST_MTIME

    EOL_UNIX = '\n'
    EOL_WINDOWS = '\r\n'
    EOL_MAC = '\r'


    def _normalize_line_endings(lines, line_ending='unix'):
    """Normalize line endings to unix (\n), windows (\r\n) or mac (\r).
    r"""Normalize line endings to unix (\n), windows (\r\n) or mac (\r).
    :param lines: The lines to normalize.
    :param line_ending: The line ending format.
    @@ -28,7 +33,62 @@ def _normalize_line_endings(lines, line_ending='unix'):
    return lines


    def _copy_file_time(source_file, destination_file):
    """Copy one file's atime and mtime to another.
    :param source_file: Source file.
    :param destination_file: Destination file.
    """
    file1, file2 = source_file, destination_file

    try:
    stat1 = os.stat(file1)
    except os.error:
    sys.stderr.write(file1 + ' : cannot stat\n')
    sys.exit(1)

    try:
    os.utime(file2, (stat1[ST_ATIME], stat1[ST_MTIME]))
    except os.error:
    sys.stderr.write(file2 + ' : cannot change time\n')
    sys.exit(2)


    def _create_temp_file(contents):
    """Create a temp file.
    :param contents: The temp file contents.
    :return: The absolute path of the created temp file.
    """
    tf = tempfile.NamedTemporaryFile(
    mode='wb', suffix='txt', delete=False)
    tf.write(contents)
    tf.close()
    return tf.name


    def _delete_file_if_exists(filepath):
    """Delete the file if it exists.
    :param filepath: The path of the file to delete.
    """
    if os.path.exists(filepath):
    os.remove(filepath)


    def _write_data_to_file(filepath, data):
    """Write data to file.
    :param filepath: The file path.
    :param data: The data to write.
    """
    f = open(filepath, 'wb')
    f.write(data)
    f.close()


    def main():
    """Main."""
    parser = argparse.ArgumentParser(
    prog='crlf',
    description='Replace CRLF (windows) line endings with LF (unix) line '
    @@ -46,6 +106,11 @@ def main():
    'CRLF (windows) line endings',
    action='store_true',
    default=False)
    parser.add_argument('-t', '--timestamps',
    help="maintains the modfified file's time stamps "
    "(atime and mtime)",
    action='store_true',
    default=False)
    parser.add_argument('files',
    nargs='+',
    metavar='<files>|<pattern>',
    @@ -111,9 +176,22 @@ def main():

    if args.dryrun is False:
    try:
    f = open(file_to_process, 'wb')
    f.write(newdata)
    f.close()
    if args.timestamps is True:
    # create a temp file with the orignal file
    # contents and copy the old file's atime a mtime
    tmp_file_path = _create_temp_file(data)
    _copy_file_time(file_to_process, tmp_file_path)

    # overwrite the current file with the modfified
    # contents
    _write_data_to_file(file_to_process, newdata)

    if args.timestamps is True:
    # copy the original file's atime and mtime back to
    # the orignial file w/ the modified contents,
    # and delete the temp file.
    _copy_file_time(tmp_file_path, file_to_process)
    _delete_file_if_exists(tmp_file_path)
    except Exception as ex:
    print('error : {0}'.format(str(ex)))
    sys.exit(1)
  12. @jonlabelle jonlabelle revised this gist Mar 20, 2017. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions crlf.py
    Original file line number Diff line number Diff line change
    @@ -128,6 +128,7 @@ def main():
    .format(file_to_process))
    else:
    print("- '{0}' : file not found".format(file_to_process))
    sys.exit(1)


    if __name__ == '__main__':
  13. @jonlabelle jonlabelle created this gist Mar 20, 2017.
    134 changes: 134 additions & 0 deletions crlf.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,134 @@
    #!/usr/bin/env python

    from __future__ import print_function

    import argparse
    import os
    import sys
    import glob

    EOL_UNIX = '\n'
    EOL_WINDOWS = '\r\n'
    EOL_MAC = '\r'


    def _normalize_line_endings(lines, line_ending='unix'):
    """Normalize line endings to unix (\n), windows (\r\n) or mac (\r).
    :param lines: The lines to normalize.
    :param line_ending: The line ending format.
    Acceptable values are 'unix' (default), 'windows' and 'mac'.
    :return: Line endings normalized.
    """
    lines = lines.replace(EOL_WINDOWS, EOL_UNIX).replace(EOL_MAC, EOL_UNIX)
    if line_ending == 'windows':
    lines = lines.replace(EOL_UNIX, EOL_WINDOWS)
    elif line_ending == 'mac':
    lines = lines.replace(EOL_UNIX, EOL_MAC)
    return lines


    def main():
    parser = argparse.ArgumentParser(
    prog='crlf',
    description='Replace CRLF (windows) line endings with LF (unix) line '
    'endings in files.')
    parser.add_argument('-q', '--quiet',
    help='surpress descriptive messages from output',
    action='store_true',
    default=False)
    parser.add_argument('-n', '--dryrun',
    help='show changes, but do not modify files',
    action='store_true',
    default=False)
    parser.add_argument('-uw', '--unix2windows',
    help='Replace LF (unix) line endings with '
    'CRLF (windows) line endings',
    action='store_true',
    default=False)
    parser.add_argument('files',
    nargs='+',
    metavar='<files>|<pattern>',
    help="a list of files, or file patterns to process. "
    "if no arguments are specified, the current "
    "directory '.' is used",
    default='.')

    if len(sys.argv) < 2:
    parser.print_help()
    sys.exit(2)

    args = parser.parse_args()

    files_to_process = []
    for argfile in args.files:
    files_to_process.extend(glob.glob(argfile))

    if len(files_to_process) <= 0:
    if args.quiet is False:
    print('No files matched the specified pattern.')
    sys.exit(0)

    if args.dryrun is True:
    print('Dry run only... files will not be modifed.')

    for file_to_process in files_to_process:
    if os.path.isdir(file_to_process):
    if args.quiet is False:
    print("- '{0}' : directory... skipped"
    .format(file_to_process))
    continue

    if os.path.isfile(file_to_process):
    data = open(file_to_process, 'rb').read()
    if '\0' in data:
    if args.quiet is False:
    print("- '{0}' : binary file... skipped".format(
    file_to_process))
    continue

    if args.unix2windows is True:
    newdata = _normalize_line_endings(data, line_ending='windows')
    else:
    newdata = _normalize_line_endings(data, line_ending='unix')

    if newdata != data:
    if args.quiet is False:
    if args.unix2windows is True:
    if args.dryrun is True:
    print("+ '{0}' : LF would be replaced with CRLF"
    .format(file_to_process))
    else:
    print("+ '{0}' : replacing LF with CRLF"
    .format(file_to_process))
    else:
    if args.dryrun is True:
    print("+ '{0}' : CRLF would be replaced with LF"
    .format(file_to_process))
    else:
    print("+ '{0}' : replacing CRLF with LF"
    .format(file_to_process))

    if args.dryrun is False:
    try:
    f = open(file_to_process, 'wb')
    f.write(newdata)
    f.close()
    except Exception as ex:
    print('error : {0}'.format(str(ex)))
    sys.exit(1)
    else:
    if args.quiet is False:
    if args.unix2windows is True:
    print("- '{0}' : line endings are already CRLF "
    "(windows)"
    .format(file_to_process))
    else:
    print("- '{0}' : line endings are already LF (unix)"
    .format(file_to_process))
    else:
    print("- '{0}' : file not found".format(file_to_process))


    if __name__ == '__main__':
    main()