我有很多文本文件分布在几个目录。 我想sorting所有文件,并创build一个文件名列表(在文本文件中),但以特定和定义的顺序。 我最初的想法是从这些目录中随机select第一个文件*1.txt
。 然后重复该过程( *2.txt, *3.txt, etc.
),直到所有文件名都在列表中。 我怎样才能在bash中做到这一点?
基础:
从1个目录中随机select文件:
shuf -n1 –e *
select1个目录中的第一个文件:
ls | sort -n | head -1
例:
更新:文件strucutre /真正的文件名格式 (这只是几个文件,有几百个)
初始指令:
media/sf_linux_sandbox/papers/ |-- semester_1 | |-- cs630-linux_research_paper-fname_lname-001.txt | |-- cs635-progamming_languages-fname_lname-002.txt | |-- cs645-java_programming_paper-fname_lname-003.txt | `-- cs900-computer_robotics_capstone-fname_lname-004.txt |-- semester_2 | |-- cs650-software_methodologies-fname_lname-001.txt | |-- cs675-nosql_db_research-fname_lname-002.txt | |-- cs700-artificial_intelligence_reasearch-fname_lname-003.txt | |-- cs800-algorithms_and_computational_complexity-fname_lname-004.txt | |-- cs825-database_systems_internals-fname_lname-005.txt | `-- cs850-computer_graphics-fname_lname-006.txt |-- semester_3 |-- cs725-web_programming_technologies-fname_lname-001.txt |-- cs750-data_programming-fname_lname-002.txt `-- cs775-hardware_software_interface_paper-fname_lname-003.txt
我正在寻找产生的输出/结果(随机洗牌的文件,但保持数字顺序):
results.txt /filepath/cs650-software_methodologies-fname_lname-001.txt /filepath/s630-linux_research_paper-fname_lname-001.txt /filepath/cs725-web_programming_technologies-fname_lname-001.txt /filepath/cs635-progamming_languages-fname_lname-002.txt /filepath/cs750-data_programming-fname_lname-002.txt /filepath/cs675-nosql_db_research-fname_lname-002.txt /filepath/cs645-java_programming_paper-fname_lname-003.txt /filepath/cs775-hardware_software_interface_paper-fname_lname-003.txt /filepath/cs700-artificial_intelligence_reasearch-fname_lname-003.txt /filepath/cs900-computer_robotics_capstone-fname_lname-004.txt /filepath/cs800-algorithms_and_computational_complexity-fname_lname-004.txt /filepath/cs825-database_systems_internals-fname_lname-005.txt /filepath/cs850-computer_graphics-fname_lname-006.txt
这将混洗源树中的所有文件,使用稳定的排序对数字部分进行部分排序,以便其他元素保持混洗。
$ target=~/tmp/shuf $ destination=/filepath/ $ tree $target ~/tmp/shuf `-- papers |-- semester_1 | |-- cs630-linux_research_paper-fname_lname-001.txt | |-- cs635-progamming_languages-fname_lname-002.txt | |-- cs645-java_programming_paper-fname_lname-003.txt | `-- cs900-computer_robotics_capstone-fname_lname-004.txt |-- semester_2 | |-- cs650-software_methodologies-fname_lname-001.txt | |-- cs675-nosql_db_research-fname_lname-002.txt | |-- cs700-artificial_intelligence_reasearch-fname_lname-003.txt | |-- cs800-algorithms_and_computational_complexity-fname_lname-004.txt | |-- cs825-database_systems_internals-fname_lname-005.txt | `-- cs850-computer_graphics-fname_lname-006.txt `-- semester_3 |-- cs725-web_programming_technologies-fname_lname-001.txt |-- cs750-data_programming-fname_lname-002.txt `-- cs775-hardware_software_interface_paper-fname_lname-003.txt 4 directories, 13 files $ find $target -type f -iname "*.txt" \ | shuf \ | awk -F- '{printf("%s:%s\n", $0, $NF)}' \ | sort -t : -k 2 -s \ | cut -d : -f 1 \ | xargs -n1 basename \ | sed "s,^,$destination," /filepath/cs725-web_programming_technologies-fname_lname-001.txt /filepath/cs650-software_methodologies-fname_lname-001.txt /filepath/cs630-linux_research_paper-fname_lname-001.txt /filepath/cs635-progamming_languages-fname_lname-002.txt /filepath/cs750-data_programming-fname_lname-002.txt /filepath/cs675-nosql_db_research-fname_lname-002.txt /filepath/cs775-hardware_software_interface_paper-fname_lname-003.txt /filepath/cs700-artificial_intelligence_reasearch-fname_lname-003.txt /filepath/cs645-java_programming_paper-fname_lname-003.txt /filepath/cs900-computer_robotics_capstone-fname_lname-004.txt /filepath/cs800-algorithms_and_computational_complexity-fname_lname-004.txt /filepath/cs825-database_systems_internals-fname_lname-005.txt /filepath/cs850-computer_graphics-fname_lname-006.txt
要将结果存储在名为filename
,可以重定向:
$ find $target -type f -iname "*.txt" \ | shuf \ | awk -F- '{printf("%s:%s\n", $0, $NF)}' \ | sort -t : -k 2 -s \ | cut -d : -f 1 \ | xargs -n1 basename \ | sed "s,^,$destination," \ > filename
我不确定我完全明白你在问什么。 你是否试图根据文件名中的尾随数字进行数字排序? 如果是这样,你将需要提供确切的规格为您的文件名,以便适当的正则表达式可以用来提取数字和从那里排序…即你的文件名总是[az] [1-9]或有多个字符,特殊字符等? 如果你能够提供你正在使用的真实路径以及确切的预期输出,那么它可能会让事情变得更容易。
要回答这个问题“从各种目录随机选择一个文件”…下面是两个非常相似的方法来显示当前目录的每个子目录中的一个随机文件的路径。
while IFS= read -r dir; do find "$dir" -maxdepth 1 -type f | shuf -n1 done < <(find -type d) > results.txt
要么…
shopt -s globstar for dir in ./**/; do find "$dir" -maxdepth 1 -type f | shuf -n1 done > results.txt shopt -u globstar
如果您需要每个随机文件的基本名称(而不是完整路径),则可以使用以下命令替换内部find
命令:
random="$(find "$dir" -maxdepth 1 -type f | shuf -n1)" [[ -n $random ]] && echo "${random##*/}"
如果你只想要选择随机的txt文件,那么只需要在内部find
命令的末尾添加选项-name '*.txt'
。
请注意,我使用了shuf命令,因为在你的问题中提到了它,但是使用$ RANDOM就可以解决这个问题。
我试图在撰写答案时匹配您在帖子中提供的输出。
#!/bin/bash usage_exit () { echo "usage: $0 <target-directory>" exit 0 } if [ $# != 1 ] ; then usage_exit fi # The pattern below searches files in the range 000 through 199. # You can change the pattern to match your needs. for n in {0..1}{0..9}{0..9} do find $1 -type f -name '*'$n'.txt' | shuf done
另一种方法是将find -type d的结果存储在数组中。 然后在数组中的任意目录中找到最大数量的常规文件,将其用作((i=1; i<=max; i++))
循环中的最大边界,在循环的每个主体中对数组进行混洗,然后遍历它复制每个目录中的$i'th
文件(如果存在的话),如果不存在(即,如果该目录具有小于$i
文件的话)。
#!/bin/bash #shuffle function taken from http://mywiki.wooledge.org/BashFAQ/026 shuffle() { local i tmp size max rand # $RANDOM % (i+1) is biased because of the limited range of $RANDOM # Compensate by using a range which is a multiple of the array size. size=${#array[*]} max=$(( 32768 / size * size )) for ((i=size-1; i>0; i--)); do while (( (rand=$RANDOM) >= max )); do :; done rand=$(( rand % (i+1) )) tmp=${array[i]} array[i]=${array[rand]} array[rand]=$tmp done } destination=/filepath max=0 shopt -s nullglob dotglob while IFS= read -d $'\0' -r dir ; do array+=("$dir") count=$(ls -F "$dir" | egrep -v "^*[/*]$" | wc -l) ((count>max)) && max=$count done < <(find . -mindepth 1 -type d -print0) for ((i=1; i<=max; i++)); do shuffle for dir in "${array[@]}"; do file=$(find "$dir" -maxdepth 1 -type f -iname '*.txt' | sort -n | awk "NR==$i") [[ -n $file ]] && echo "$destination/$file" done done
例
> tree . ├── script ├── semester_1 │ ├── cs630-linux_research_paper-fname_lname-001.txt │ ├── cs635-progamming_languages-fname_lname-002.txt │ ├── cs645-java_programming_paper-fname_lname-003.txt │ └── cs900-computer_robotics_capstone-fname_lname-004.txt ├── semester_2 │ ├── cs650-software_methodologies-fname_lname-001.txt │ ├── cs675-nosql_db_research-fname_lname-002.txt │ ├── cs700-artificial_intelligence_reasearch-fname_lname-003.txt │ ├── cs800-algorithms_and_computational_complexity-fname_lname-004.txt │ ├── cs825-database_systems_internals-fname_lname-005.txt │ └── cs850-computer_graphics-fname_lname-006.txt └── semester_3 ├── cs725-web_programming_technologies-fname_lname-001.txt ├── cs750-data_programming-fname_lname-002.txt └── cs775-hardware_software_interface_paper-fname_lname-003.txt 3 directories, 14 files > ./script /filepath/cs725-web_programming_technologies-fname_lname-001.txt /filepath/cs650-software_methodologies-fname_lname-001.txt /filepath/cs630-linux_research_paper-fname_lname-001.txt /filepath/cs750-data_programming-fname_lname-002.txt /filepath/cs635-progamming_languages-fname_lname-002.txt /filepath/cs675-nosql_db_research-fname_lname-002.txt /filepath/cs645-java_programming_paper-fname_lname-003.txt /filepath/cs775-hardware_software_interface_paper-fname_lname-003.txt /filepath/cs700-artificial_intelligence_reasearch-fname_lname-003.txt /filepath/cs900-computer_robotics_capstone-fname_lname-004.txt /filepath/cs800-algorithms_and_computational_complexity-fname_lname-004.txt /filepath/cs825-database_systems_internals-fname_lname-005.txt /filepath/cs850-computer_graphics-fname_lname-006.txt
我认为这可能是有用的:
dir='some/directory' file=`/bin/ls -1 "$dir" | sort --random-sort | head -1` path=`readlink --canonicalize "$dir/$file"` # Converts to full path echo "The randomly-selected file is: $path"
考虑看看下面的问题 。
希望能帮助到你。
克莱门西奥·莫拉莱斯·卢卡斯。