简体   繁体   中英

Looping through a pattern for use in a bash find command

I'm trying to write a simple bash script to look through a directory and delete all versions of a file (except the latest 2) that match a pattern. This command works great:

find . -type f -name 'a.*.log' -printf '%T@\t%p\n' \
  | sort -t $'\t' -g \
  | head -n -2 \
  | cut -d $'\t' -f 2- \
  | xargs rm -f

This will take the following files: a.1.log, a.2.log, and a.3.log, and delete a.1.log (assuming it's the oldest by timestamp). The version portion of the filename is a hash, so not numerically in order (I changed it for simplicity).

So, what I want to do is loop through a set of different patterns and feed each one to the find command above. I've simplified the script for this example to look like this:

#!/bin/bash
FILES="a.*.log
b.*.log
c.*.log"

for f in $FILES
do
    echo "Processing $f"
    find . -type f -name "$f"
done

The directory I'm running this from has these files:

a.1.log, a.2.log, a.3.log, b.1.log, b.2.log, b.3.log, c.1.log, c.2.log, c.3.log

The output I get from the above script is:

Processing a.1.log
./a.1.log
Processing a.2.log
./a.2.log
Processing a.3.log
./a.3.log
Processing b.1.log
./b.1.log
Processing b.2.log
./b.2.log
Processing b.3.log
./b.3.log
Processing c.1.log
./c.1.log
Processing c.2.log
./c.2.log
Processing c.3.log
./c.3.log

What I need is for the output to look like this:

Processing a.*.log
./a.1.log
./a.2.log
./a.3.log
Processing b.*.log
./b.1.log
./b.2.log
./b.3.log
Processing c.*.log
./c.1.log
./c.2.log
./c.3.log

I've tried using an array instead of looping through a string, escaping the file patterns, using single vs double quotes in the find, etc... But I can't get it to simply substitute the pattern into the find. If I run the finds individually by hand, it gives me the output I'm looking for:

$ find . -type f -name "a.*.log"
./a.1.log
./a.2.log
./a.3.log
$ find . -type f -name "b.*.log"
./b.1.log
./b.2.log
./b.3.log
$ find . -type f -name "c.*.log"
./c.1.log
./c.2.log
./c.3.log

I can't find any examples of someone looping through a collection of patterns and substituting them into a command. Any help would be awesome.

Thanks.

the problem you encounter is that without quotes variable is split but also file globbing occurs, this can be avoided using shell option noglob set -f , or using an array and using double quotes :

files=( 'a.*.log' 'b.*.log' 'c.*.log' )

for f in "${files[@]}"; do
...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM