如何将包含 NULL 的文件移动到单独的文件夹?

如何将包含 NULL 的文件移动到单独的文件夹?

我文件夹中有超过 10000 个文件。我使用 Rscript 预处理这些文件。它显示错误:

read.table(wd, comment.char ="#", header=T, sep='\t') 中的错误:文件开头为空

当我在文本编辑器中打开该文件时,该文件是空的,但文件大小约为 4 MB。接下来,我在 Notepad++ 中打开该文件,我能够看到以下内容NULL NULL NULL ... NULL

文件示例

我想将这类文件从文件夹移动到另一个文件夹。我该怎么做?

答案1

测试单个文件

grep如果以下命令some_file至少包含一个空字符,则返回退出状态 0:

<some_file tr -dc '\0' | tr '\0' '\n' | grep -q ''

除非设置了 shell 选项,否则,如果s exit.默认未设置,而您希望这样,则pipefail的退出状态grep将成为整个管道的退出状态(请参阅trpipefail否则会发生什么)。

我写“如果trs 退出”,是因为grep退出后第二个tr需要写入一些内容才能获得 SIGPIPE;然后第一个tr需要写入一些内容才能获得 SIGPIPE;只有这样管道才被视为终止。tr即使grep提前退出并且结果已知,第一个也可能会继续读取。如果some_file是一个生成永无止境的字节流的特殊文件(类似于/dev/urandom),并且流中没有足够的空字节,则管道将永远不会退出。对于常规文件,最坏的情况是第一个在tr读取整个文件后退出。如果some_file是一个常规文件,那么trs 将退出最终一定。

我的这个答案解释了一个可以加快速度的技巧。对于你的情况,这个技巧会将tr(s) 留在后台。由于你要测试许多文件,因此堆积trs 不是一个好主意。

实际上,测试文件的最开头通常就足够了。以下命令将读取最多 2 KiB 的内容some_file并仅分析此部分:

head -c 2048 some_file | tr -dc '\0' | tr '\0' '\n' | grep -q ''

或者,您可以使用命令file,对于大文件,它也不会读取整个文件。如果file --mime-type不打印,我们在这里生成退出状态 0 text/whatever

! file --brief --mime-type some_file | grep -q 'text/'

我希望这两个命令在绝大多数情况下能够一致;但在某些情况下(文件)它们可能会有所不同。


测试多个文件(并进行相应移动)

此代码片段将循环遍历当前工作目录中的文件,测试常规文件并相应地移动它们:

#!/bin/bash
(
shopt -s nullglob
for f in ./*; do
   [ -f "$f" ] \
   && ! [ -L "$f" ] \
   && head -c 2048 "$f" | tr -dc '\0' | tr '\0' '\n' | grep -q '' \
   && mv -v "$f" /target/directory/
done
)

笔记:

  • 预先創建/target/directory/

  • 您可以使用其他测试。相关行将是:

       && ! file --brief --mime-type "$f" | grep -q 'text/' \
    
  • 子 shell(…)适用于您想要将代码粘贴到交互式 shell 的情况。有了子 shell,代码不会更改当前 shell 中的任何内容。

  • 通常*不匹配隐藏文件。附加dotglob到该shopt -s行以*匹配隐藏文件。

  • 如果您想要递归,请附加globstarshopt -s行并使用./**而不是./*。请注意,如果有同名文件,则可能会丢失数据;请考虑mv -i

  • 我们想要有条件地移动常规文件。[ -f "$f" ]检查我们处理的是否是常规文件;但对于指向常规文件的符号链接(指向常规文件的符号链接(指向常规文件的符号链接(…))),它也会成功。这就是我们额外检查文件是否不是符号链接的原因( )。如果您希望代码将指向常规文件的符号链接视为常规文件,请删除包含(包括终止换行符)! [ -L "$f" ]的整行。[ -L

  • 一般而言,此答案中的命令和代码不可移植。您标记了并说操作系统是 Ubuntu,我利用了 Bash 和 Ubuntu 提供的功能。

  • 解决方案find是可能的。我们的每个测试都是一个管道,因此find无论如何都必须生成 shell。

相关内容