Bash 只查找多个目录中的第一个文件

Bash 只查找多个目录中的第一个文件,bash,unix,awk,command-line,find,Bash,Unix,Awk,Command Line,Find,我有很多目录: 13R 613 AB1 ACT AMB ANI 每个目录包含大量文件: 20140828.13R.file.csv.gz 20140829.13R.file.csv.gz 20140830.13R.file.csv.gz 20140831.13R.file.csv.gz 20140901.13R.file.csv.gz 20131114.613.file.csv.gz 20131115.613.file.csv.gz 20131116.613.file.csv.gz 2013

我有很多目录:

13R
613
AB1
ACT
AMB
ANI
每个目录包含大量文件:

20140828.13R.file.csv.gz
20140829.13R.file.csv.gz
20140830.13R.file.csv.gz
20140831.13R.file.csv.gz
20140901.13R.file.csv.gz

20131114.613.file.csv.gz
20131115.613.file.csv.gz
20131116.613.file.csv.gz
20131117.613.file.csv.gz

20141114.ab1.file.csv.gz
20141115.ab1.file.csv.gz
20141116.ab1.file.csv.gz
20141117.ab1.file.csv.gz

etc..
目的是从每个目录中获取第一个文件

我期望的结果是:

13R|20140828
613|20131114
AB1|20141114
这是文件名中的目录名和日期。 我想我需要一个查找和头部命令+awk,但我做不到,我需要你的帮助

这是我的测试结果

for f in $(ls -1);do ls -1 $f/ | head -1;done
但是缺少文件夹名

当我指的是第一个文件时,是在文件夹中按字母顺序返回的第一个文件


谢谢。

您可以通过Bash循环来实现这一点

鉴于:

/tmp/test
/tmp/test/dir_1
/tmp/test/dir_1/file_1
/tmp/test/dir_1/file_2
/tmp/test/dir_1/file_3
/tmp/test/dir_2
/tmp/test/dir_2/file_1
/tmp/test/dir_2/file_2
/tmp/test/dir_2/file_3
/tmp/test/dir_3
/tmp/test/dir_3/file_1
/tmp/test/dir_3/file_2
/tmp/test/dir_3/file_3
/tmp/test/file_1
/tmp/test/file_2
/tmp/test/file_3
只需在目录中循环,从一个glob中形成一个数组并获取第一个:

prefix="/tmp/test"
cd "$prefix"
for fn in dir_*; do 
    cd "$prefix"/"$fn"
    arr=(*)
    echo "$fn|${arr[0]}"
done
印刷品:

dir_1|file_1
dir_2|file_1
dir_3|file_1
如果您对“first”的定义与Bash的不同,那么在获取第一个元素之前,只需根据您的定义对数组进行排序


您还可以使用
find
awk
执行此操作:

$ find /tmp/test -mindepth 2 -print0 | awk -v RS="\0" '{s=$0; sub(/[^/]+$/,"",s); if (s in paths) next; paths[s]; print $0}'
/tmp/test/dir_1/file_1
/tmp/test/dir_2/file_1
/tmp/test/dir_3/file_1

然后插入一个
排序
(或使用
gawk
)按需排序

您可以使用Bash循环来完成此操作

鉴于:

/tmp/test
/tmp/test/dir_1
/tmp/test/dir_1/file_1
/tmp/test/dir_1/file_2
/tmp/test/dir_1/file_3
/tmp/test/dir_2
/tmp/test/dir_2/file_1
/tmp/test/dir_2/file_2
/tmp/test/dir_2/file_3
/tmp/test/dir_3
/tmp/test/dir_3/file_1
/tmp/test/dir_3/file_2
/tmp/test/dir_3/file_3
/tmp/test/file_1
/tmp/test/file_2
/tmp/test/file_3
只需在目录中循环,从一个glob中形成一个数组并获取第一个:

prefix="/tmp/test"
cd "$prefix"
for fn in dir_*; do 
    cd "$prefix"/"$fn"
    arr=(*)
    echo "$fn|${arr[0]}"
done
印刷品:

dir_1|file_1
dir_2|file_1
dir_3|file_1
如果您对“first”的定义与Bash的不同,那么在获取第一个元素之前,只需根据您的定义对数组进行排序


您还可以使用
find
awk
执行此操作:

$ find /tmp/test -mindepth 2 -print0 | awk -v RS="\0" '{s=$0; sub(/[^/]+$/,"",s); if (s in paths) next; paths[s]; print $0}'
/tmp/test/dir_1/file_1
/tmp/test/dir_2/file_1
/tmp/test/dir_3/file_1

并插入一个
排序
(或使用
gawk
)按需排序

排序
具有唯一选项。只有目录应该是唯一的,所以使用排序
-k1,1
中的第一个字段。当文件列表已排序时,该解决方案有效

printf "%s\n" */* | sort -k1,1 -t/ -u | sed 's#\(.*\)/\([0-9]*\).*#\1|\2#'

当日期字段后面可能跟有另一个数字时,您需要更改
sed
命令。

sort
具有唯一选项。只有目录应该是唯一的,所以使用排序
-k1,1
中的第一个字段。当文件列表已排序时,该解决方案有效

printf "%s\n" */* | sort -k1,1 -t/ -u | sed 's#\(.*\)/\([0-9]*\).*#\1|\2#'
当日期字段后面可能跟有另一个数字时,您需要更改
sed
命令。

这对我很有用:

for dir in $(find "$FOLDER" -type d); do
  FILE=$(ls -1 -p $dir | grep -v / | head -n1)
  if [ ! -z "$FILE" ]; then
    echo "$dir/$FILE"
  fi
done
这对我很有用:

for dir in $(find "$FOLDER" -type d); do
  FILE=$(ls -1 -p $dir | grep -v / | head -n1)
  if [ ! -z "$FILE" ]; then
    echo "$dir/$FILE"
  fi
done

StackOverflow是帮助人们修复他们现有的代码,任何代码,都不一定是完美的。您感觉使用
查找、头部、awk
非常接近一个好主意。因此,添加一些代码,人们会帮助您修复它。另外,当您显示所需的输出时,您对目录中的“第一个文件”使用的实际“规则”是什么?按名称排序,或按目录中创建的第一个文件排序(因为创建日期不保留在Unix文件系统中)。请用关键信息更新你的Q。祝你好运。还有,你说的第一个文件到底是什么意思?加上一些代码,让我们知道你说的“第一个文件”是什么意思。祝你好运。StackOverflow是帮助人们修复他们现有的代码,任何代码,都不一定是完美的。您感觉使用
查找、头部、awk
非常接近一个好主意。因此,添加一些代码,人们会帮助您修复它。另外,当您显示所需的输出时,您对目录中的“第一个文件”使用的实际“规则”是什么?按名称排序,或按目录中创建的第一个文件排序(因为创建日期不保留在Unix文件系统中)。请用关键信息更新你的Q。祝你好运。还有,你说的第一个文件到底是什么意思?加上一些代码,让我们知道你说的“第一个文件”是什么意思。祝你好运