shell 如何在Linux文件系统中找到dos格式文件

ekqde3dh  于 2023-11-21  发布在  Shell
关注(0)|答案(8)|浏览(149)

我想知道目录中的哪些文件是dos文本文件(而不是unix文本文件)。具体来说,这些文件在Vim中打开时,底部的栏会显示类似"filename.php" [dos] [noeol]的内容
我试过find . -name "*.php" | xargs grep ^M -l,但没有得到可靠的结果,特别是,它不能检测到某些没有^M字符的dos文件。
有更好的选择吗?

syqv5f0l

syqv5f0l1#

怎么样:

find . -name "*.php" | xargs file | grep "CRLF"

字符串
我认为尝试使用^M来尝试查找文件是不可靠的。

2w2cym1i

2w2cym1i2#

不知道你说的“不可靠”到底是什么意思,但你可能想试试:

find . -name '*.php' -print0 | xargs -0 grep -l '^M$'

字符串
这使用了更友好的 atrocious-filenames-with-spaces-in-them-friendly 选项,并且只在行尾之前找到回车符。
请记住,^M是一个CTRLM字符,而不是两个字符。
它还将列出即使有 * 一 * 行处于DOS模式的文件,这可能是您想要的,因为这些文件可能是被非UNIX编辑器损坏的UNIX文件。
根据您的更新,Vim将您的文件报告为DOS格式:
如果Vim * 报告为DOS格式,那么 every line以CRLF结尾。这就是vim的工作方式。如果甚至 one line没有CR,那么它被认为是UNIX格式,并且^M字符在缓冲区中可见。如果它是所有DOS格式,则不显示^M字符:
Vim将同时查找dos和unix行结束符,但Vim内置了对unix的偏好。

  • 如果文件中的所有行都以CRLF结尾,则将应用dos文件格式,这意味着当将行阅读到缓冲区中时,将删除每个CRLF,并且缓冲区'ff'选项将为dos。
  • 如果一行或多行仅以LF结尾,则将应用unix文件格式,这意味着删除每个LF(但每个CR将存在于缓冲区中,并将显示为^M),并且缓冲区'ff'选项将是unix。
    如果你真的想知道文件里有什么,不要依赖像Vim这样太聪明的工具:-)
    用途:
od -xcb input_file_name | less


自己检查行尾

zbsbpyhn

zbsbpyhn3#

我很幸运,

find . -name "*.php" -exec grep -Pl "\r" {} \;

字符串

sg24os4d

sg24os4d4#

这很像你最初的解决方案;因此,它可能更容易让你记住:

find . -name "*.php" | xargs grep "\r" -l

字符串

思考过程:

在Vim中,要删除^M,请键入:

%s:/^M//g


其中,^是Ctrl键,M是ENTER键。但我从来不记得要打印该序列所需的键,所以我总是使用以下命令删除它们:

%s:/\r//g


所以我的推论是\r和^M是等价的,前者更容易记住。

prdp8dxp

prdp8dxp5#

如果您的dos2unix命令有-i选项,则可以使用该功能在具有DOS换行符的目录中查找文件。

$ man dos2unix
.
.
.
     -i[FLAGS], --info[=FLAGS] FILE ...
           Display file information. No conversion is done.

    The following information is printed, in this order:
    number of DOS line breaks,
    number of Unix line breaks,
    number of Mac line breaks,
    byte order mark,
    text or binary, file name.
.
.
.
Optionally extra flags can be set to change the (-i) output.
.
.
.
           c   Print only the files that would be converted.

字符串
下面的一行脚本如下:

  • find此目录树中的所有文件,
  • 对所有文件运行dos2unix以确定要更改的文件,
  • 对要更改的文件运行dos2unix

$ find . -type f | xargs -d '\n' dos2unix -ic | xargs -d '\n' dos2unix

n6lpvg4x

n6lpvg4x6#

我一直在使用cat -e来查看文件的行尾。
使用^M作为一个单一的CTRLM字符并没有真正为我工作(它的工作原理就好像我只是按回车键,没有实际插入不可打印的^M行结束-用echo ' CTRLM ' | cat -e测试),所以我最终做的可能看起来太多了,但它确实完成了工作:

grep '$' *.php | cat -e | grep '\^M\$' | sed 's/:.*//' | uniq

字符串
得双曲余切值.

  • 第一个grep只是在每个文件的每一行前添加文件名(可以用awk '{print FILENAME, $0}'替换,但是grep在我的文件集上工作得更快);
  • cat -e显式打印不可打印的行结尾;
  • 第二个grep查找以^M$结尾的行,^M * 是两个字符 *;
  • sed部分仅保留文件名(可以替换为cut -d ':' -f 1);
  • uniq只保留每个文件名一次。
ubof19bj

ubof19bj7#

GNU find

find . -type f -iname "*.php"  -exec file "{}" + | grep CRLF

字符串
我不知道你找到那些DOS php文件后想做什么,但是如果你想把它们转换成unix,那么

find . -type f -iname "*.php"  -exec dos2unix "{}" +;


就可以了,不需要专门检查是不是DOS文件。

svgewumm

svgewumm8#

如果你希望Vim告诉你哪些文件是这种格式的,你可以使用下面的脚本:

"use this script to check which files are in dos format according to vim
"use: in the folder that you want to check
"create a file, say res.txt
"> vim -u NONE --noplugins res.txt
"> in vim: source this_script.vim

python << EOF
import os
import vim

cur_buf =  vim.current.buffer

IGNORE_START = ''.split()
IGNORE_END = '.pyc .swp .png ~'.split()

IGNORE_DIRS = '.hg .git dd_ .bzr'.split()

for dirpath, dirnames, fnames in os.walk(os.curdir):
  for dirn in dirnames:
    for diri in IGNORE_DIRS:
      if dirn.endswith(diri):
        dirnames.remove(dirn)
        break
  for fname in fnames:
    skip = False
    for fstart in IGNORE_START:
      if fname.startswith(fstart):
        skip = True
    for fend in IGNORE_END:
      if fname.endswith(fend):
        skip = True
    if skip is True:
      continue
    fname = os.path.join(dirpath, fname)
    vim.command('view {}'.format(fname))
    curr_ff = vim.eval('&ff')
    if vim.current.buffer != cur_buf:
      vim.command('bw!')
    if curr_ff == 'dos':
      cur_buf.append('{} {}'.format(curr_ff, fname))
EOF

字符串
你的Vim需要用python编译(python是用来循环文件夹中的文件的,可能有一个更简单的方法来做到这一点,但我真的不知道。

相关问题