我有很多目录;其中很多文件只有1个或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 ..
将目录上移一个,但是是否可以在subset
中上移和下移而不使用完整路径mv $dir complete_path/subset
?
答案 0 :(得分:3)
如果要处理任意目录名称和内容,则有很多陷阱和陷阱。这段Shellcheck干净的代码试图避免所有这些:
#! /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 ]] && continue
)的目录中。如果该假设不正确,请删除该行。find ... | wc -l
可能无法正常工作。请参见How can I get a count of files in a directory using the command line?。find
("./$dir//."
)所困扰的第一个参数旨在避免多个陷阱。引号可以防止目录名称中的特殊字符引起问题。如果目录名称以./
开头,则-
前缀避免将参数视为选项。后缀//.
意味着find
找到的每个文件在一行上都只有一个'//',因此grep -c //
将准确地计算文件数。--
和mkdir
命令的mv
参数是为了确保如果$dir
或$destdir
以{{1}开头的话,它们可以正常工作。 }(这会使它们被视为选项)。参见Bash Pitfalls #2 (cp $file $target)。答案 1 :(得分:0)
这是到目前为止我提出的最好的解决方案。
我想知道是否有更优雅的解决方案:
#!/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
答案 2 :(得分:0)
您的一般方法很好。不幸的是,没有一种明显优越的方法可以计算目录中有多少文件。
您可以通过遍历-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
调用来完成所有这些操作,但是现在我们肯定在 arcane 地区。
find . -type d \
-exec bash -c '(($(compgen -G "$1/*" | wc -l) > 2))' bash {} \; \
-exec mv {} subset/ \;
命令
mv $dir ..
将目录上移一个,但是是否可以在subset
中上移和下移而不使用完整路径mv $dir complete_path/subset
?
您尚未更改目录,因此请使用所需的任何相对路径。如果我理解这个问题,它可能很简单,例如mv <dir> subset/
。