Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List only common parent directories for files

Tags:

linux

bash

shell

I am searching for one file, say "file1.txt", and output of find command is like below.

/home/nicool/Desktop/file1.txt
/home/nicool/Desktop/dir1/file1.txt
/home/nicool/Desktop/dir1/dir2/file1.txt

In above cases I want only common parent directory, which is "/home/nicool/Desktop" in above case. How it can be achieved using bash? Please help to find general solution for such problem.

like image 369
Nicool Avatar asked Sep 29 '22 21:09

Nicool


2 Answers

This script reads lines and stores the common prefix in each iteration:

# read a line into the variable "prefix", split at slashes
IFS=/ read -a prefix

# while there are more lines, one after another read them into "next",
# also split at slashes
while IFS=/ read -a next; do
    new_prefix=()

    # for all indexes in prefix
    for ((i=0; i < "${#prefix[@]}"; ++i)); do
        # if the word in the new line matches the old one
        if [[ "${prefix[i]}" == "${next[i]}" ]]; then
            # then append to the new prefix
            new_prefix+=("${prefix[i]}")
        else
            # otherwise break out of the loop
            break
        fi
    done

    prefix=("${new_prefix[@]}")
done

# join an array
function join {
    # copied from: http://stackoverflow.com/a/17841619/416224
    local IFS="$1"
    shift
    echo "$*"
}

# join the common prefix array using slashes
join / "${prefix[@]}"

Example:

$ ./x.sh <<eof
/home/nicool/Desktop1/file1.txt
/home/nicool/Desktop2/dir1/file1.txt
/home/nicool/Desktop3/dir1/dir2/file1.txt
eof
/home/nicool
like image 113
kay Avatar answered Oct 03 '22 02:10

kay


I don't think there's a bash builtin for this, but you can use this script, and pipe your find into it.

read -r FIRSTLINE
DIR=$(dirname "$FIRSTLINE")

while read -r NEXTLINE; do
  until [[ "${NEXTLINE:0:${#DIR}}" = "$DIR" || "$DIR" = "/" ]]; do
    DIR=$(dirname "$DIR")
  done
done

echo $DIR

For added safety, use -print0 on your find, and adjust your read statements to have -d '\0'. This will work with filenames that have newlines.

like image 33
Jeff Bowman Avatar answered Oct 03 '22 00:10

Jeff Bowman