2014-09-12 16 views
5

Sto cercando un file, diciamo "file1.txt", e l'output del comando find è come di seguito.Elenca solo le directory padre comuni per i file

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

Nei casi di cui sopra voglio directory padre solo comune, che è "/ home/nicool/Desktop" nel caso di cui sopra. Come può essere raggiunto usando bash? Si prega di aiutare a trovare una soluzione generale per tale problema.

risposta

2

Questo script legge linee e memorizza il prefisso comune in ogni iterazione:

# 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[@]}" 

Esempio:

$ ./x.sh <<eof 
/home/nicool/Desktop1/file1.txt 
/home/nicool/Desktop2/dir1/file1.txt 
/home/nicool/Desktop3/dir1/dir2/file1.txt 
eof 
/home/nicool 
1
lcp() { 
    local prefix path 
    read prefix 

    while read path; do 
     while ! [[ $path =~ ^"$prefix" ]]; do 
      [[ $prefix == $(dirname "$prefix") ]] && return 1 
      prefix=$(dirname "$prefix") 
     done 
    done 

    printf '%s\n' "$prefix" 
    return 0 
} 

Trova il prefisso comune più lungo di tutte le righe di input standard.

$ find/-name file1.txt | lcp 
/home/nicool/Desktop 
1

Io non credo che ci sia un builtin bash per questo, ma si puoi usare questo script e instradare il tuo find in esso.

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 

Per maggiore sicurezza, utilizzare -print0 sul ritrovamento, e regolare le dichiarazioni read avere -d '\0'. Questo funzionerà con nomi di file che hanno newline.

Problemi correlati