我正在为我正在建设的管道编写一个shell脚本。代码应该只从目录中获取10个唯一文件标识符的列表,然后开始对它们进行一些分析。代码确实以我抓取的10个文件开头,然后继续在整个目录上运行!代码如下:
第一个基本用户输入
#!/bin/bash
Dir=$1 #needs directory containing the input files
然后将10个唯一标识符放入列表
if [ -e file_list.txt ] #remove any list at the start
then
rm file_list.txt
fi
for file in `ls ${Dir}* | cut -f 6 -d '/' | cut -f 1 -d '_' | uniq | head` #grab the first 10 unique files and put them in a text file
do
echo $file >> file_list.txt #each file set has a unique tag, write that out to the list
done
现在查看文件列表并执行操作
while read file #now iterate through the list of files
do
#do stuff to file here
ls ${file}* #list every file with this tag; just an example
done < file_list.txt
我想说,当我抓住10个文件名时,罪魁祸首就是调用uniq
。在使用uniq之前,此代码的早期版本没有此问题。但我不知道除非这对我的file_list.txt
做了一些奇怪的事情,这对我来说很好。
当我处理第三个代码块中的文件时,错误是否存在?
我使用了shellcheck并且我得到了很多注释&#34;双引号以防止通配和分词。&#34;
答案 0 :(得分:2)
关于&#34;为什么&#34; - 如果不知道你的文件名,几乎不可能说出来。例如,名称前面带有文字*
的任何文件都将被原始代码扩展为目录中的每个其他文件的列表。而不是跟踪破坏代码的原因,而是首先编写一些遵循最佳实践的内容更为明智,因此您不需要深入了解不应该使用的功能的蜿蜒路径。从脚本中使用可以在创造不必要的混乱中相互影响。
在我阅读时,您希望根据其名称前第一个_
之前的内容为每个文件分配一个标记,然后使用前10个唯一标记获取文件。
我们可以做到这一点。它可能看起来像这样:
#!/usr/bin/env bash
case $BASH_VERSION in ''|[0-3].*) echo "ERROR: Needs bash 4.0 or later" >&2; exit 1;; esac
Dir=$1
files=( "$Dir"/*_* ) # collect files w/ underscores in our directory in an array
declare -A example_per_tag=( ) # create a map from tag to full filename
for file in "${files[@]}"; do # iterate over the array of files
basename=${file##*/} # take off the directory name to get the basename
tag=${basename%%_*} # take off the first _ and everything after to get the tag
example_per_tag[$tag]=$file # store a link from that tag to the file in our map
done
# can't slice a list of keys from an associative array, so we need an indexed array w/ them
tags=( "${!example_per_tag[@]}" ) # collect only the keys -- the tags -- in an array
# now, iterate over only the first 10 tags
for tag in "${tags[@]:0:10}"; do
echo "For tag $tag, our example file is ${example_per_tag[$tag]}"
done
注意这里的所有引用;我们不引用的唯一地方是:
*_*
),我们希望它扩展而不是作为文字处理。