Bash 复制包含2个以上文件的目录

Bash 复制包含2个以上文件的目录,bash,Bash,我有很多目录;很多文件中只有一个或两个文件 我想在另一个目录中复制包含2个以上文件的目录,如何检查并移动目录 到目前为止,我已经写了剧本,但我不确定 #!/bin/bash mkdir "subset" for dir in *; do #if the file is a directory if [ -d "$dir" ]; then #count number of files count=$(find "$d

我有很多目录;很多文件中只有一个或两个文件

我想在另一个目录中复制包含2个以上文件的目录,如何检查并移动目录

到目前为止,我已经写了剧本,但我不确定

#!/bin/bash

mkdir "subset"
for dir in *; do
        #if the file is a directory
        if [ -d "$dir" ]; then
            #count number of files
            count=$(find "$dir" -type f | wc -l)
            #if count>=2 then move
            if [ "$count" -ge 2 ]; then
                #move dir
                #   ...
            fi
        fi
done


命令mv$dir。。将目录从一个向上移动,但是否可以在不使用完整路径mv$dir complete\u path/subset的情况下在子集中从一个向上移动和向下移动?

这是迄今为止最好的解决方案

我想知道是否有更优雅的解决方案:

#!/bin/bash

mkdir "OOOO3_LESS_THAN_TWO"

for dir in *; do
        #if the file is a directory
        if [ -d "$dir" ]; then
            #count number of files
            count=$(find "$dir" -type f | wc -l)
            #if count<=2 then move
            if [ "$count" -le 2 ]; then
                #move dir
                mv -v "$dir" /completepath/"OOOO3_LESS_THAN_TWO"
            fi
        fi
done

这是迄今为止我找到的最好的解决方案

我想知道是否有更优雅的解决方案:

#!/bin/bash

mkdir "OOOO3_LESS_THAN_TWO"

for dir in *; do
        #if the file is a directory
        if [ -d "$dir" ]; then
            #count number of files
            count=$(find "$dir" -type f | wc -l)
            #if count<=2 then move
            if [ "$count" -le 2 ]; then
                #move dir
                mv -v "$dir" /completepath/"OOOO3_LESS_THAN_TWO"
            fi
        fi
done

你的一般方法很好。不幸的是,在计算一个目录中有多少个文件时,没有明显优于此的方法

您可以通过在*/上循环来摆脱-d检查。尾随的/表示只匹配目录

你可以把作业和测试结合起来。你可能会喜欢它或者觉得它看起来很奇怪

你也可以用。。。做算术。我个人觉得它更具可读性

for dir in */; do
    if count=$(find "$dir" -type f | wc -l) && ((count >= 2)); then
        ...
    fi
done
或者可以完全省略count变量

for dir in */; do
    if (($(find "$dir" -type f | wc -l) >= 2)); then
        ...
    fi
done
这一切都可以在一次发现中完成,但现在我们肯定处于神秘领域

find . -type d \
    -exec bash -c '(($(compgen -G "$1/*" | wc -l) > 2))' bash {} \; \
    -exec mv {} subset/ \;
命令mv$dir。。将目录上移一个,但是否可以在不使用完整路径mv$dir complete\u path/subset的情况下在子集中上移一个和下移一个


您没有更改目录,所以请使用您喜欢的任何相对路径。如果我理解这个问题,它可能会像mv subset/

一样简单,您的一般方法很好。不幸的是,在计算一个目录中有多少个文件时,没有明显优于此的方法

您可以通过在*/上循环来摆脱-d检查。尾随的/表示只匹配目录

你可以把作业和测试结合起来。你可能会喜欢它或者觉得它看起来很奇怪

你也可以用。。。做算术。我个人觉得它更具可读性

for dir in */; do
    if count=$(find "$dir" -type f | wc -l) && ((count >= 2)); then
        ...
    fi
done
或者可以完全省略count变量

for dir in */; do
    if (($(find "$dir" -type f | wc -l) >= 2)); then
        ...
    fi
done
这一切都可以在一次发现中完成,但现在我们肯定处于神秘领域

find . -type d \
    -exec bash -c '(($(compgen -G "$1/*" | wc -l) > 2))' bash {} \; \
    -exec mv {} subset/ \;
命令mv$dir。。将目录上移一个,但是否可以在不使用完整路径mv$dir complete\u path/subset的情况下在子集中上移一个和下移一个


您没有更改目录,所以请使用您喜欢的任何相对路径。如果我理解这个问题,它可能很简单,如mv subset/

如果你想处理任意目录名和内容,有很多陷阱和陷阱。这段干净的代码试图避免所有这些问题:

#! /bin/bash -p

shopt -s nullglob   # glob patterns that match nothing expand to nothing
shopt -s dotglob    # glob patterns expand names that start with '.'

destdir='subset'

[[ -d $destdir ]] || mkdir -- "$destdir"

for dir in * ; do
    [[ -L $dir ]] && continue               # Skip symbolic links
    [[ -d $dir ]] || continue               # Skip non-directories
    [[ $dir -ef $destdir ]] && continue     # Skip the destination dir.

    numfiles=$(find "./$dir//." -type f -print | grep -c //)
    (( numfiles > 2 )) && mv -v -- "$dir" "$destdir"
done
shopt-s nullglob意味着如果在空目录中运行代码,代码将正常工作。否则,它将尝试处理名为“*”的虚假目录项。 shopt-s dotglob使代码能够处理名称以“.”开头的目录,例如.mydir。 您可以在代码后面通过将循环保护更改为for dir in*/…,来避免目录检查,但这会使符号链接的检查稍微复杂化。 代码假定您不想将符号链接移动到包含两个以上文件[[-L$dir]]]的目录(&C)继续。如果该假设不正确,请删除该行。 计算一个目录下的文件数很棘手,因为文件名中可能有换行符,这意味着find…|wc-l可能无法正常工作。看见要查找的第一个复杂参数。/$dir//。旨在避免几个陷阱。引号防止目录名中的特殊字符引起问题。如果目录名以-,则./prefix避免将参数视为选项。/。后缀意味着对于find找到的每个文件,一行中正好有一个“/”,因此grep-c//将准确地计算文件的数量。 mkdir和mv命令的-参数用于确保如果$dir或$destdir以-开头,则它们可以正常工作,这将导致它们被视为选项。看见
如果您想要处理任意目录名和内容,那么会有许多陷阱和陷阱。这段干净的代码试图避免所有这些问题:

#! /bin/bash -p

shopt -s nullglob   # glob patterns that match nothing expand to nothing
shopt -s dotglob    # glob patterns expand names that start with '.'

destdir='subset'

[[ -d $destdir ]] || mkdir -- "$destdir"

for dir in * ; do
    [[ -L $dir ]] && continue               # Skip symbolic links
    [[ -d $dir ]] || continue               # Skip non-directories
    [[ $dir -ef $destdir ]] && continue     # Skip the destination dir.

    numfiles=$(find "./$dir//." -type f -print | grep -c //)
    (( numfiles > 2 )) && mv -v -- "$dir" "$destdir"
done
shopt-s nullglob意味着如果在空目录中运行代码,代码将正常工作。否则,它将尝试处理名为“*”的虚假目录项。 shopt-s dotglob使代码能够处理名称以“.”开头的目录,例如.mydir。 您可以在代码后面通过将循环保护更改为for dir in*/…,来避免目录检查,但这会使符号链接的检查稍微复杂化。 代码假定您不想将符号链接移动到包含两个以上文件[[-L$dir]]]的目录(&C)继续。如果该假设不正确,请删除该行。 计算一个目录下的文件数很棘手,因为文件名中可能有换行符,这意味着find…|wc-l可能无法正常工作。看见骗局 要查找的第一个参数为./$dir//。旨在避免几个陷阱。引号防止目录名中的特殊字符引起问题。如果目录名以-,则./prefix避免将参数视为选项。/。后缀意味着对于find找到的每个文件,一行中正好有一个“/”,因此grep-c//将准确地计算文件的数量。 mkdir和mv命令的-参数用于确保如果$dir或$destdir以-开头,则它们可以正常工作,这将导致它们被视为选项。看见
在我看来很合理。mv$dir toDir将移动目录和文件。运行脚本时会发生什么情况?count似乎有效,但如果toDir与脚本在同一目录中,我不确定它是否有效,并且我不知道父目录中某个目录的mv命令如何。您的文件计数需要注意。出于同样的原因,你应该小心寻找。因此,与其说:寻找-类型f | wc-l我将使用find-最大深度1-f型-打印f A | wc-c@kvantour明目张胆地插上插头,但你可以使用我的,它的存在正是因为这个原因:DLooks对我来说是合理的。mv$dir toDir将移动目录和文件。运行脚本时会发生什么情况?count似乎有效,但如果toDir与脚本在同一目录中,我不确定它是否有效,并且我不知道父目录中某个目录的mv命令如何。您的文件计数需要注意。出于同样的原因,你应该小心寻找。因此,与其说:寻找-类型f | wc-l我将使用find-最大深度1-f型-打印f A | wc-c@kvantour明目张胆地插在前面,但你可以使用我的,它的存在正是因为这个原因:D