带 while 循环 shell 脚本的egrep

带 while 循环 shell 脚本的egrep

我有目录中的文件列表/tmp/drop。我已将我的问题的基本要素纳入其中test script zz.sh。我已经截取了脚本的一部分并将其放在这里。这些是列出的文件和行 - 当它赋予 while 循环时 - 如何file只为变量分配文件名而不是这些行中的各种其他字符串?

任何帮助将不胜感激,并且对其他人也有帮助。

machine001:/home/aaa999999> ls -l /tmp/drop | grep "2017-01-29" | egrep  '\.gz$' | tail -10
+ ls -F -l /tmp/drop
+ tail -10
+ grep 2017-01-29
+ egrep \.gz$
-rw-r--r--   1 user1001      user1001           20 Jan 29  2017 pattern101_worker-2_2017-01-29-21:33:13.888.complete.gz
-rw-r--r--   1 user1001      user1001           20 Jan 29  2017 pattern101_worker-2_2017-01-29-21:48:14.632.complete.gz
-rw-r--r--   1 user1001      user1001           20 Jan 29  2017 pattern101_worker-2_2017-01-29-22:03:19.098.complete.gz
-rw-r--r--   1 user1001      user1001           20 Jan 29  2017 pattern101_worker-2_2017-01-29-22:18:19.416.complete.gz
-rw-r--r--   1 user1001      user1001           20 Jan 29  2017 pattern101_worker-2_2017-01-29-22:33:19.878.complete.gz
-rw-r--r--   1 user1001      user1001           20 Jan 29  2017 pattern101_worker-2_2017-01-29-22:48:25.636.complete.gz
-rw-r--r--   1 user1001      user1001           20 Jan 29  2017 pattern101_worker-2_2017-01-29-23:03:26.515.complete.gz
-rw-r--r--   1 user1001      user1001           20 Jan 29  2017 pattern101_worker-2_2017-01-29-23:18:28.279.complete.gz
-rw-r--r--   1 user1001      user1001           20 Jan 29  2017 pattern101_worker-2_2017-01-29-23:33:33.059.complete.gz
-rw-r--r--   1 user1001      user1001           20 Jan 29  2017 pattern101_worker-2_2017-01-29-23:48:33.841.complete.gz
machine001:/home/aaa999999> cat zz.sh
+ cat zz.sh
#!/bin/bash
set -x

DROP_DIR=/tmp/drop
ARCHIVE_DIR=/tmp/arch
YESTERDAY="2017-01-29"
# move from drop dir
ls -1 ${DROP_DIR} | grep ${YESTERDAY} | egrep '\.gz$' | while read file; do
    mv  ${DROP_DIR}/$file ${ARCHIVE_DIR}
        echo 'File name is ' ${file}
done

答案1

ls -1仅打印文件名。ls -l还打印一堆其他东西。另一个是数字一,另一个是小写字母 el。

尽管-1这里是不必要的,因为如果输出重定向到管道,则隐含“单列”模式。

ls但实际上,您根本不需要这里的管道。该循环可以替换为:

for file in "$DROP_DIR/"*"$YESTERDAY"*.gz ; do 
    mv "$file" "$ARCHIVE_DIR"
    echo "File name is ${file#$DROP_DIR/}"
done

也可以看看:解析L在 Greg 的 Bash 维基上。

答案2

使用 GNU 的建议date

yesterday=$( date -d yesterday +%F )
drop_dir=/tmp/drop
archive_dir=/tmp/arch

mkdir -p "$archive_dir"

mv -f "$drop_dir"/*"$yesterday"*.gz "$archive_dir"

在这里,"$drop_dir"/*"$yesterday"*.gz将扩展到与给定模式匹配的所有文件。只要模式扩展到几千个字符,这就会起作用,在这种情况下,shell 将抱怨“参数列表太长”。

或者,如果您确实想在移动时循环输出每个文件名(仅将mv上面的命令更改为以下命令):

for name in "$drop_dir"/*"$yesterday"*.gz; do
    [ -f "$name" ] || continue
    mv "$name" "$archive_dir"
    printf 'Moved "%s"\n' "$name"
done

在这里,for循环将迭代与上一个变体中使用的相同名称,但一个接一个。每个名称都将保存在$name(包括目录名称)中。如果没有与该模式匹配的文件,该模式将保持未展开状态。这就是为什么我们$name在移动之前进行显式测试以确保它确实与现有文件相对应。

或者,与find

find "$drop_dir" -maxdepth 1 -type f -name "*$yesterday*.gz" \
    -print -exec mv {} "$archive_dir" ';'

在这里,将从对应于常规文件 ( ) 且与给定的模式匹配的名称find中选取名称。对于每个这样的名称,调用将文件移动到目标文件夹中。但在调用之前,将在终端上列出文件名(包括路径)。$drop_dir-type f-namemvmv-print

-maxdepth 1选项停止find递归到 的子文件夹中$drop_dir

答案3

你的问题对我来说不太清楚,但我认为你似乎正在寻找的是-o你的egrep陈述的选项:

 egrep -o "[^[:space:]]+\.gz$"

选项-o( --only-matching) 导致egrep仅输出匹配行的匹配部分。匹配[^[:space:]]除空格字符之外的任何内容。

相关内容