I'm trying to write a script that will loop through all subfolders of a directory to search for a specific file and then copy a new file to those folders that contain that file.

This is what I have so far:

#!/bin/sh
dir=/Documents
find "$dir" -name Sample.doc -printf "%p\n" | sort -nr | while read -r i; do
  echo "$i"
  done

This works to list all the Sample.doc files and their folders within the Documents folder.

However, I cannot find a way to extract the path from those folders to copy the new file into them.

Any help would be appreciated.

The dirname command removes the filename from the full path

I think you are almost there. You can replace %p with %h in the -printf expression :

%h : Leading directories of file's name (all but the last element). If the file name contains no slashes (since it is in the current directory) the %h specifier expands to ".".

so the command would be something like :

find "$dir" -name Sample.doc -printf "%h\n" | sort -nr | while read -r i; do cp SomeFile "$i"; done

by the way, why is the sort part needed ?

Using %h instead %p has already been suggested in another answer, but I'd like to add some improvements to make your code more robust. If, for instance, a matching directory contains a newline character in its name, you will in the best-case end up missing directories and getting some error messages from cp. At worst, you might override files anywhere on your system.

So instead, try doing it like this:

find "$dir" -name Sample.doc -printf "%h\0" | xargs --null -L1 cp SomeFile

The ACSII zero is guaranteed to never show up in any filenames, so unlike \n it works as a reliable separator for passing the paths. --null tells xargs to use the \0 as a input delimiter. It will then execute the given command (cp Somefile) once per item passed through the pipe, while appending the respective item as additional argument.

In bash:

shopt -s nullglob globstar
for i in "$dir"/**/Sample.doc
do
    cp 'new file' "$(dirname "$i")"/
done

In fish:

for i in $dir/**Sample.doc
    cp 'new file' (dirname $i)/
end

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.