larry_lasers
larry_lasers

Reputation: 3

After finding a file, how to write parent directory name to new file?

I'm working on a bash script which searches through subdirectories for each instance of a file and then concatenates the contents of each to a single file. When writing each file, I would first like to write the name of each parent directory before the content, i.e.,

Find: path/to/parentdir/file.txt
Write:
parentdir
<contents of file>

So far, I can find the files and get their contents but I am getting tripped up on extracting the directory name. Best attempt:

find . -type f -name file.txt -exec echo "$(dirname {})" \; -exec cat {} \; >> bigfile.txt

But this just results in a lot of '.'s.

Any advice greatly appreciated.

Upvotes: 0

Views: 483

Answers (1)

markp-fuso
markp-fuso

Reputation: 34324

Assumptions:

  • the first 2 lines of OP's sample output (Find: ... and Write: ...) are not actually part of what gets written to bigfile.txt
  • OP has no requirement to preface the parent directory names with any special strings/patterns to make them standout from the rest of the text in bigfile.txt

If these assumptions are wrong we can come back and add some code to the answer.


UPDATE: Revisiting after realizing that dirname (as referenced by OP) is not providing the desired output (ie, dirname provides entire directory structure while OP just wants the name of the immediate parent directory).

One awk idea to parse the filename as well as cat the file:

awk '
BEGIN { n=split(ARGV[1],arr,"/")        # split name of input dir/file by "/"; put contents in array arr[]
        print arr[n-1]                  # print next-to-last element from arr[]
      }
1                                       # pass all input lines to stdout
' path/to/dir/filename

Pulling this into OP's find command:

find . -type f -name file.txt -exec awk 'BEGIN {n=split(ARGV[1],arr,"/"); print arr[n-1]}1' {} \; >> bigfile.txt

Previous answer based on assumption dirname was providing what the OP wanted ...

There's no need to invoke a sub-process to call dirname, and also no need to echo said results; just call dirname directly, eg:

find . -type f -name file.txt -exec dirname {} \; -exec cat {} \; >> bigfile.txt

[Adding @oguzismail's comment ...]

With GNU find you can use the -printf option to eliminate the dirname calls, eg:

find . -type f -name file.txt -printf '%h\n' -exec cat {} \; >> bigfile.txt

Upvotes: 1

Related Questions