Bash: 检查目录是否只包含具有特定后缀的文件
Bash: Check if a directory contains only files with a specific suffix
我正在尝试编写一个脚本来检查目录是否仅包含
一种特定类型的文件(and/or 文件夹),return 1 表示错误,0 表示正确。
IE:我想检查 /my/dir/
是否仅包含 *.gz
个文件而没有其他内容。
这是我目前所拥有的,但它似乎没有按预期工作:
# Basic vars
readonly THIS_JOB=${0##*/}
readonly ARGS_NBR=1
declare dir_in=
dir_in="/*.gz"
#echo $dir_in
files=$(shopt -s nullglob dotglob; echo ! $dir_in)
echo $files
if (( ${#files} ))
then
echo "Success: Directory contains files."
exit 0
else
echo "Failure: Directory is empty (or does not exist or is a file)"
exit 1
fi
I want to check if /my/dir/ contains only *.gz files and nothing else.
使用 find
而不是球化。使用 find
和解析查找输出确实更容易。球化对于简单的脚本来说很简单,但是一旦你想解析 "all files in a directory" 并进行一些过滤等,使用 find
:
会更容易(也更安全)
find "" -mindepth 1 -maxdepth 1 \! -name '*.gz' -o \! -type f | wc -l | xargs test 0 -eq
这会在目录中找到所有未命名为 *.gz
或不是文件的 "things"(因此 mkdir a.gz
被计算在内),对它们进行计数,然后测试它们是否'重新计数等于0。如果计数等于0,xargs test 0 -eq
就会return0,如果不等于,就会return状态在1 - 125
之间。如果愿意,您可以使用简单的 || return 1
处理非零 return 状态。
您可以通过简单的 bash 替换删除 xargs
并使用 this thread 中的方法进行一点加速并获得 test
return 值,这是 0
或 1
:
[ 0 -eq "$(find "" -mindepth 1 -maxdepth 1 \! -name '*.gz' -o \! -type f -print '.' | wc -c)" ]
请记住,脚本的退出状态是最后执行的命令的退出状态。因此,如果您愿意,您的脚本中不需要任何其他内容,只需一个 shebang 和这个 oneliner 就足够了。
由于您使用的是 bash,因此您可以使用另一个设置:GLOBIGNORE
#!/bin/bash
containsonly(){
dir=""
glob=""
if [ ! -d "$dir" ]; then
echo 1>&2 "Failure: directory does not exist"
return 2
fi
local res=$(
cd "$dir"
GLOBIGNORE=$glob"
shopt -s nullglob dotglob
echo *
)
if [ ${#res} = 0 ]; then
echo 1>&2 "Success: directory contains no extra files"
return 0
else
echo 1>&2 "Failure: directory contains extra files"
return 1
fi
}
# ...
containsonly myfolder '*.gz'
使用 Bash 的 extglob
、!(*.gz)
和 grep
:
$ if grep -qs . path/!(*.gz) ; then echo yes ; else echo nope ; fi
man grep
:
-q, --quiet, --silent
Quiet; do not write anything to standard output. Exit
immediately with zero status if any match is found, even if an
error was detected. Also see the -s or --no-messages option.
-s, --no-messages
Suppress error messages about nonexistent or unreadable files.
有些人建议计算所有不匹配 globbing 模式的文件 *.gz
。根据文件的数量,这可能效率很低。对于您的工作,只需找到一个与您的通配模式不匹配的文件就足够了。使用find
的-quite
动作在第一个匹配后退出:
if [ -z "$(find /usr/share/man/man1/* -not -name '*.gz' -print -quit)" ]
then echo only gz
fi
我正在尝试编写一个脚本来检查目录是否仅包含 一种特定类型的文件(and/or 文件夹),return 1 表示错误,0 表示正确。
IE:我想检查 /my/dir/
是否仅包含 *.gz
个文件而没有其他内容。
这是我目前所拥有的,但它似乎没有按预期工作:
# Basic vars
readonly THIS_JOB=${0##*/}
readonly ARGS_NBR=1
declare dir_in=
dir_in="/*.gz"
#echo $dir_in
files=$(shopt -s nullglob dotglob; echo ! $dir_in)
echo $files
if (( ${#files} ))
then
echo "Success: Directory contains files."
exit 0
else
echo "Failure: Directory is empty (or does not exist or is a file)"
exit 1
fi
I want to check if /my/dir/ contains only *.gz files and nothing else.
使用 find
而不是球化。使用 find
和解析查找输出确实更容易。球化对于简单的脚本来说很简单,但是一旦你想解析 "all files in a directory" 并进行一些过滤等,使用 find
:
find "" -mindepth 1 -maxdepth 1 \! -name '*.gz' -o \! -type f | wc -l | xargs test 0 -eq
这会在目录中找到所有未命名为 *.gz
或不是文件的 "things"(因此 mkdir a.gz
被计算在内),对它们进行计数,然后测试它们是否'重新计数等于0。如果计数等于0,xargs test 0 -eq
就会return0,如果不等于,就会return状态在1 - 125
之间。如果愿意,您可以使用简单的 || return 1
处理非零 return 状态。
您可以通过简单的 bash 替换删除 xargs
并使用 this thread 中的方法进行一点加速并获得 test
return 值,这是 0
或 1
:
[ 0 -eq "$(find "" -mindepth 1 -maxdepth 1 \! -name '*.gz' -o \! -type f -print '.' | wc -c)" ]
请记住,脚本的退出状态是最后执行的命令的退出状态。因此,如果您愿意,您的脚本中不需要任何其他内容,只需一个 shebang 和这个 oneliner 就足够了。
由于您使用的是 bash,因此您可以使用另一个设置:GLOBIGNORE
#!/bin/bash
containsonly(){
dir=""
glob=""
if [ ! -d "$dir" ]; then
echo 1>&2 "Failure: directory does not exist"
return 2
fi
local res=$(
cd "$dir"
GLOBIGNORE=$glob"
shopt -s nullglob dotglob
echo *
)
if [ ${#res} = 0 ]; then
echo 1>&2 "Success: directory contains no extra files"
return 0
else
echo 1>&2 "Failure: directory contains extra files"
return 1
fi
}
# ...
containsonly myfolder '*.gz'
使用 Bash 的 extglob
、!(*.gz)
和 grep
:
$ if grep -qs . path/!(*.gz) ; then echo yes ; else echo nope ; fi
man grep
:
-q, --quiet, --silent
Quiet; do not write anything to standard output. Exit
immediately with zero status if any match is found, even if an
error was detected. Also see the -s or --no-messages option.
-s, --no-messages
Suppress error messages about nonexistent or unreadable files.
有些人建议计算所有不匹配 globbing 模式的文件 *.gz
。根据文件的数量,这可能效率很低。对于您的工作,只需找到一个与您的通配模式不匹配的文件就足够了。使用find
的-quite
动作在第一个匹配后退出:
if [ -z "$(find /usr/share/man/man1/* -not -name '*.gz' -print -quit)" ]
then echo only gz
fi