我有目录中的文件列表/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
-name
mv
mv
-print
该-maxdepth 1
选项停止find
递归到 的子文件夹中$drop_dir
。
答案3
你的问题对我来说不太清楚,但我认为你似乎正在寻找的是-o
你的egrep
陈述的选项:
egrep -o "[^[:space:]]+\.gz$"
选项-o
( --only-matching
) 导致egrep
仅输出匹配行的匹配部分。匹配[^[:space:]]
除空格字符之外的任何内容。