【问题标题】:How to copy files that having line number > 100 to other folder如何将行号> 100的文件复制到其他文件夹
【发布时间】:2016-07-11 05:43:42
【问题描述】:

我想将 100 行或更多的文件复制到另一个文件夹:

$ cd "/home/john/folder a"  
$ wc -l *
10 file1.txt
50 file2.txt
100 file3.txt
150 file4.txt

我想将文件file3.txtfile4.txt(100 行或更多的文件)复制到文件夹/home/john/folder b

有人可以帮帮我吗?非常感谢。

【问题讨论】:

    标签: shell file unix copy


    【解决方案1】:

    试试这个:

    declare -i numfile
    for f in *; do
      numfile=$([ -f "$f" ] && cat "$f" | wc -l )
      [ $numfile -ge 100 ] && cp "$f" otherdir
    done
    

    对于当前目录中的每个文件,numfile 被分配了文件的行数。

    如果numfile 大于或等于100,则将文件复制到otherdir

    编辑:

    正如 William Pursell 所提到的,一种更可靠的方法是在执行比较和复制命令之前测试该项目是否是一个文件:

    for f in *; do 
      if [ -f "$f" ]; then
        [ "$(wc -l < $f)" -ge 100 ] && cp "$f" otherdir;
      fi
    done
    

    【讨论】:

    • 我想你的回答肯定比我的更中肯:)
    • 依赖 numfile 声明为整数闻起来很糟糕。例如,如果测试反向复制少于 100 行的文件,这将尝试复制目录。将&amp;&amp; 附加在进行numfile 分配的行的末尾可能更安全,或者写for f in *; do test -f "$f" &amp;&amp; test "$(wc -l &lt; $f)" -ge 100 &amp;&amp; cp "$f" /path; done
    • [ -f "$f" ] 是什么意思?
    • @Jiangty [ -f "$f" ] 用于检查分配给"$f" 变量的项目是否为常规文件:-f。查看更多:File test operators
    【解决方案2】:

    还有一个:

    # Assuming that we are in source folder ...
    cp $(wc -l *|grep -Eo '[0-9]{3,} (.*)'|head -n -1|cut -d ' ' -f 2) /dev/null "/home/john/folder b"
    

    head 删除由wc 打印的total 行,/dev/null 处理您没有任何符合条件的文件的情况。

    当然,这个解决方案 - 就像这里介绍的其他解决方案一样 - 会给您带来问题,如果您的源目录包含这么多文件,则会超过最大命令行长度。

    【讨论】:

    • 我喜欢这个想法,但使用正则表达式匹配进行数值比较似乎很脆弱。可能更容易做到wc -l * | awk '$1 &gt; 100{print $2}' ... 目录仍然存在问题。
    • 在我的解决方案中,目录被隐式忽略。我也没有看到数字的正则表达式匹配有问题,除了一个(有点病态的情况),我的方法会失败:想象一个名为 200 xx 的文件(即名称以三位数开头并且有嵌入空间);使用我的解决方案,即使文件少于 100 行也会被复制。当然,谁会创建名称中包含嵌入空格的文件.... ;-)
    【解决方案3】:

    试试这样的(POSIX sh):

    #!/bin/sh
    SOURCE_FOLDER="/home/john/folder a"
    COPY_TO="/home/john/folder b"
    
    for dir in "$SOURCE_FOLDER" "$COPY_TO"; do
        if [ ! -d "$dir" ]; then
            echo "Directory ${dir} does not exist." >&2
            exit 1
        fi
    done
    
    if [ "x`ls -A "$SOURCE_FOLDER"`" = "x" ]; then
        echo "Directory '${SOURCE_FOLDER}' is empty." >&2
        exit 1
    fi
    
    for file in "$SOURCE_FOLDER"/*; do
        LINES=`wc -l < "$file"`
        echo "File ${file} has ${LINES} lines..."
    
        if [ "$LINES" -ge 100 ]; then
            echo "Copying ${file}..."
            cp -a "$file" "${COPY_TO}/"
        fi
    done
    

    这里有一个 Bash 版本,适用于带有 Bash 的系统(你说的是 Unix,而不是 Linux,所以你可能想要最高版本):

    #!/bin/bash
    SOURCE_FOLDER="/home/john/folder a"
    COPY_TO="/home/john/folder b"
    
    for dir in "$SOURCE_FOLDER" "$COPY_TO"; do
        if [[ ! -d "$dir" ]]; then
            echo "Directory ${dir} does not exist." >&2
            exit 1
        fi
    done
    
    if [[ -z "$(ls -A "$SOURCE_FOLDER")" ]]; then
        echo "Directory '${SOURCE_FOLDER}' is empty." >&2
        exit 1
    fi
    
    for file in "$SOURCE_FOLDER"/*; do
        LINES="$(wc -l < "$file"')"
        echo "File ${file} has ${LINES} lines..."
    
        if [[ "$LINES" -ge 100 ]]; then
            echo "Copying ${file}..."
            cp -a "$file" "${COPY_TO}/"
        fi
    done
    

    我是这样测试的:

    $  mkdir "folder a"
    $  mkdir "folder b"
    $  chmod +x script.sh
    $  cd folder\ a/
    $  seq 1 1000 > file1.txt
    $  seq 1 1000 > file2.txt
    $  seq 1 100 > file4.txt
    $  seq 1 100 > file3.txt
    $  seq 1 99 > file4.txt
    $  seq 1 1 > file5.txt
    $  seq 1 20 > file6.txt
    $  cd ..
    $ ./script.sh
    File /.../dev/scratch/stack/folder a/file1.txt has 1000 lines...
    Copying /.../dev/scratch/stack/folder a/file1.txt...
    File /.../dev/scratch/stack/folder a/file2.txt has 1000 lines...
    Copying /.../dev/scratch/stack/folder a/file2.txt...
    File /.../dev/scratch/stack/folder a/file3.txt has 100 lines...
    Copying /.../dev/scratch/stack/folder a/file3.txt...
    File /.../dev/scratch/stack/folder a/file4.txt has 99 lines...
    File /.../dev/scratch/stack/folder a/file5.txt has 1 lines...
    File /.../dev/scratch/stack/folder a/file6.txt has 20 lines...
    

    我鼓励您逐行执行此操作,弄清楚脚本的每个部分是如何工作的,以帮助您将来完成类似的任务。

    我将在这里解释一些事情:

    • wc -l &lt; "$file" 只给我们文件的行数,没有文件名。
    • 如果文件中至少有 100 行,[ "$LINES" -ge 100 ] 为真。
    • echo "..." &gt;&amp;2 将一行输出到标准错误而不是标准输出。
    • cp -a 复制文件,同时保留其所有属性,例如所有者、权限和修改时间。
    • 确保引用所有变量,除非您有充分的理由不这样做,以防止出现空格问题。

    【讨论】:

    • 您不需要管道来获取行数。 wc -l &lt;"$file" 也可以。
    猜你喜欢
    • 2016-02-28
    • 1970-01-01
    • 2021-04-29
    • 1970-01-01
    • 1970-01-01
    • 2020-07-10
    • 1970-01-01
    • 2019-05-05
    • 1970-01-01
    相关资源
    最近更新 更多