Bash 如何避免列出不存在的文件时出错?

Bash 如何避免列出不存在的文件时出错?,bash,Bash,我在文件名中按日期对文件进行分组,并按组进行处理 for m in {01..12}; do for d in {01..31}; do f=`ls ./mydir/2018.${m}.${d}T*.jpg` # process files done done 但是,如果某些日期不存在文件,则代码会引发错误,例如 ls:无法访问“2018.01.20T*.jpg”:没有此类文件或目录 如何跳过缺少的日期?启用nullglob以便不匹配的通配符扩展为零。然后,您可以简单地

我在文件名中按日期对文件进行分组,并按组进行处理

for m in {01..12}; do
  for d in {01..31}; do
    f=`ls ./mydir/2018.${m}.${d}T*.jpg`
    # process files
  done
done
但是,如果某些日期不存在文件,则代码会引发错误,例如

ls:无法访问“2018.01.20T*.jpg”:没有此类文件或目录


如何跳过缺少的日期?

启用
nullglob
以便不匹配的通配符扩展为零。然后,您可以简单地对匹配的文件进行迭代

shopt -s nullglob

for m in {01..12}; do
  for d in {01..31}; do
    for f in ./mydir/2018.${m}.${d}T*.jpg; do
      # process file
    done
  done
done
如果要同时使用所有文件名,请将它们存储在一个文件夹中。数组优于普通字符串,因为它们可以处理带有空格和其他特殊字符的文件名

shopt -s nullglob

for m in {01..12}; do
  for d in {01..31}; do
    files=(./mydir/2018.${m}.${d}T*.jpg)
    # process files
    echo "processing ${files[@]}..."
  done
done


什么是最干净的方法来本地化shopt,以便在此块之后将nullglob恢复为其原始(未知)值

使用子shell:用括号围绕块。子shell创建一个子进程,确保更改不会泄漏到父进程中

(
    shopt -s nullglob
    ...
)

无论何时更改shell选项,这样做都是礼貌的,而且它是
pushd
+
popd
的优雅替代品。请注意,任何变量赋值都是子shell的局部赋值,因此在这里要小心。

启用
nullglob
以便不匹配的通配符扩展为零。然后,您可以简单地对匹配的文件进行迭代

shopt -s nullglob

for m in {01..12}; do
  for d in {01..31}; do
    for f in ./mydir/2018.${m}.${d}T*.jpg; do
      # process file
    done
  done
done
如果要同时使用所有文件名,请将它们存储在一个文件夹中。数组优于普通字符串,因为它们可以处理带有空格和其他特殊字符的文件名

shopt -s nullglob

for m in {01..12}; do
  for d in {01..31}; do
    files=(./mydir/2018.${m}.${d}T*.jpg)
    # process files
    echo "processing ${files[@]}..."
  done
done


什么是最干净的方法来本地化shopt,以便在此块之后将nullglob恢复为其原始(未知)值

使用子shell:用括号围绕块。子shell创建一个子进程,确保更改不会泄漏到父进程中

(
    shopt -s nullglob
    ...
)

无论何时更改shell选项,这样做都是礼貌的,而且它是
pushd
+
popd
的优雅替代品。请注意,任何变量赋值都是子shell的局部变量,因此在这里要小心。

这里有另一种方法,使用find:

find ./mydir/ -type f -regextype sed -regex ".*2018\.[0-9]\{,2\}\.[0-9]\{,2\}T.*\.jpg.*" -exec echo "---{}" \;
假设如下:

$ ls -l mydir/
total 0
-rw-r--r-- 1  0 Jan 23 16:46 2018.01.20Thellowet.jpg
-rw-r--r-- 1  0 Jan 23 16:47 2018.04.24Thellowet.jpg
-rw-r--r-- 1  0 Jan 23 16:46 some_random_crap
-rw-r--r-- 1  0 Jan 23 16:46 wet
-rw-r--r-- 1  0 Jan 23 16:46 when
-rw-r--r-- 1  0 Jan 23 16:46 who
-rw-r--r-- 1  0 Jan 23 16:46 wtf
使用查找:

find ./mydir/ -type f -regextype sed -regex ".*2018\.[0-9]\{,2\}\.[0-9]\{,2\}T.*\.jpg.*" -exec echo "---{}" \;
给出(通过将
--
附加到文件名来对数据进行次要处理):

注意:这也将返回具有
2018.00.xy
2018.xy.00
的文件,其中x和y可以是0到9之间的任意数字


Regex解释说:
*
:任何图案

[0-9]{,2}
:一个两位数的数字


\
用于转义特殊字符。

这里是另一种方法,使用find:

shopt -s nullglob

for m in {01..12}; do
  for d in {01..31}; do
    files=(./mydir/2018.${m}.${d}T*.jpg)
    # process files
    echo "processing ${files[@]}..."
  done
done
find ./mydir/ -type f -regextype sed -regex ".*2018\.[0-9]\{,2\}\.[0-9]\{,2\}T.*\.jpg.*" -exec echo "---{}" \;
假设如下:

$ ls -l mydir/
total 0
-rw-r--r-- 1  0 Jan 23 16:46 2018.01.20Thellowet.jpg
-rw-r--r-- 1  0 Jan 23 16:47 2018.04.24Thellowet.jpg
-rw-r--r-- 1  0 Jan 23 16:46 some_random_crap
-rw-r--r-- 1  0 Jan 23 16:46 wet
-rw-r--r-- 1  0 Jan 23 16:46 when
-rw-r--r-- 1  0 Jan 23 16:46 who
-rw-r--r-- 1  0 Jan 23 16:46 wtf
使用查找:

find ./mydir/ -type f -regextype sed -regex ".*2018\.[0-9]\{,2\}\.[0-9]\{,2\}T.*\.jpg.*" -exec echo "---{}" \;
给出(通过将
--
附加到文件名来对数据进行次要处理):

注意:这也将返回具有
2018.00.xy
2018.xy.00
的文件,其中x和y可以是0到9之间的任意数字


Regex解释说:
*
:任何图案

[0-9]{,2}
:一个两位数的数字


\
用于转义特殊字符。

错误消息被发送到stdout(fd#2),因此只需将stdout重定向到
/dev/null
,例如:
ls./mydir/2018.${m}.${d}T*.jpg 2>/dev/null
;另一种选择是在尝试
ls
之前测试文件的存在性,但这会使通配符(*)变得有点混乱,因此最简单的方法(imo)是将stdout(fd#2)重定向到
/dev/null
;我还假设无论进程文件包含什么,它都知道如何处理空的
${f}
错误消息被发送到stdout(fd#2),所以只需将stdout重定向到
/dev/null
,例如:
ls./mydir/2018.${m}.${d}T*.jpg 2>/dev/null
;另一种选择是在尝试
ls
之前测试文件的存在性,但这会使通配符(*)变得有点混乱,因此最简单的方法(imo)是将stdout(fd#2)重定向到
/dev/null
;我还假设无论
#进程文件
需要什么,它都知道如何处理空的
${f}
什么是最干净的方法来本地化shopt,以便在这个块之后将nullglob恢复到它以前的值?什么是最干净的方法来本地化shopt,以便在这个块之后将nullglob恢复到它以前的值?
shopt -s nullglob

for m in {01..12}; do
  for d in {01..31}; do
    files=(./mydir/2018.${m}.${d}T*.jpg)
    # process files
    echo "processing ${files[@]}..."
  done
done