0

I am trying to use the find command to gather files with a variable name as part of the title and move them to another directory. It is a loop variable representing an array, like so

for i in "${array[@]}"; do
   find -name "${i}r.TXT" -a -name "${i}f.TXT" -execdir mv '{}' logs/ \;
done

The directory I am trying to move them to is a subdirectory of my current working directory, named logs. What is the correct way to integrate the variable into the filename so that find will grab the correct files and move them to the logs directory?

The elements of the array are integers, like 50, 55, 60, 65, so on and I want files that are 50f, 50r, 55f, 55r, etc.

2
  • 2
    you don't want -a (which means and) but -o (or). And I'm not sure you need find. Commented Dec 4, 2020 at 7:04
  • 1
    find searches subdirectories (and subsubdirectories and ...), so it may find the files in the current directory, move them down into logs/, then find them again in logs/, move them down into logs/logs/ (or at least try to), etc. Commented Dec 4, 2020 at 8:14

1 Answer 1

1

As pointed out in the comments, -a was the problem here. find -name 1 -a -name 2 is the same as find -name 1 -name 2 and will never print anything because the name cannot be 1 and 2 at the same time. You could use -o instead, but there is a simplier solution:

Use find -name "${i}[fr].TXT" to find the files 50f.TXT and 50r.TXT when i=50.

Please note Gordon Davisson's comment:

find searches subdirectories (and subsubdirectories and ...), so it may find the files in the current directory, move them down into logs/, then find them again in logs/, move them down into logs/logs/ (or at least try to), etc

To prevent this, you can exclude directories named log by adding -name logs -prune -o as the first arguments to find.

However, if all your files are in the current working directory you don't need find at all.
Globs can do the same:

shopt -s failglob
for i in "${array[@]}"; do
   mv "${i}"[fr].TXT logs/
done

Failglob will print an error message if no matching file was found. You can leave it out, but then the resulting command mv logs/ will print an error message.

Sign up to request clarification or add additional context in comments.

7 Comments

What if instead of moving the files to a directory, I wanted to rename them with mv? So for example something like: mv "${i}[fr].TXT "${i}[fr]1.TXT and just add an extra number to the end of the file.
Unless you use a tool like perl-rename you have do a single mv for every file. Use a nested loop and parameter expansions: for i in "${array[@]}"; do for f in "${i}"[fr].TXT; do mv "$f" "${f/./1.}"; done; done.
By the way: If you use the array only in this context you could replace it with a brace expansion. That way you don't need a loop at all for moving the files to logs/, or only one loop to rename them: shopt -s nullglob; for f in {50,55,60,65}[fr].TXT; do ....
So for some reason, the mv command is not renaming the files I want. I am using it within an if statement to ensure that the $i value is an integer for i in "${array[@]}"; do if [ "$i" == "$number" ]; then for f in "${i}"[fr].TXT; do mv "$f" "${f/./1.}"; done; fi done; where $number is the regex '^[0-9]+$'
Regex matching is done with [[ "$stringVar" =~ $regexVar ]]. You did a plain string comparison. Note the double [[ and un(!)quoted $regexVar.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.