Linux: Find all symlinks of a given 'original' file? (reverse 'readlink')

后端 未结 6 2037
遥遥无期
遥遥无期 2020-12-04 11:33

Consider the following command line snippet:

$ cd /tmp/
$ mkdir dirA
$ mkdir dirB
$ echo \"the contents of the \'original\' file\" > orig.file
$ ls -la o         


        
相关标签:
6条回答
  • 2020-12-04 11:36

    Symlinks do not track what is pointing to a given destination, so you cannot do better than checking each symlink to see if it points to the desired destination, such as

    for i in *; do
        if [ -L "$i" ] && [ "$i" -ef /tmp/orig.file ]; then
            printf "Found: %s\n" "$i"
        fi
    done
    
    0 讨论(0)
  • 2020-12-04 11:46

    Inspired by Gordon Davisson's comment. This is similar to another answer, but I got the desired results using exec. I needed something that could find symbolic links without knowing where the original file was located.

    find / -type l -exec ls -al {} \; | grep -i "all_or_part_of_original_name"
    
    0 讨论(0)
  • 2020-12-04 11:48

    I've not seen a command for this and it's not an easy task, since the target file contains zero information on what source files point to it.

    This is similar to "hard" links but at least those are always on the same file system so you can do a find -inode to list them. Soft links are more problematic since they can cross file systems.

    I think what you're going to have to do is basically perform an ls -al on every file in your entire hierarchy and use grep to search for -> /path/to/target/file.

    For example, here's one I ran on my system (formatted for readability - those last two lines are actually on one line in the real output):

    pax$ find / -exec ls -ald {} ';' 2>/dev/null | grep '\-> /usr/share/applications'
    lrwxrwxrwx 1 pax pax 23 2010-06-12 14:56 /home/pax/applications_usr_share
                                             -> /usr/share/applications
    
    0 讨论(0)
  • 2020-12-04 12:00

    This may be too simplistic for what you want to do, but I find it useful. it does Not answer your question literally, as it's not 'run on the original file', but it accomplishes the task. But, a lot more HDD access. And, it only works for 'soft' linked files which is majority of user linked files.

    from the root of you data storage directory or users data directories, wherever symlinked 'files' to the orig.file may reside, run the find command:

    # find -type l -ls |grep -i 'orig.file' 
    

    or

    # find /Starting/Search\ Path/ -type l -ls |grep -i '*orig*'
    

    I would Normally use part of the name eg, '*orig*' to start, because we know users will rename (prefix) a simply named file with a more descriptive one like " Jan report from London _ orig.file.2015.01.21 " or something.

    Note: I've Never gotten the -samefile option to work for me.

    clean, simple, easy to remember

    hope this helps Someone. Landis.

    0 讨论(0)
  • 2020-12-04 12:01

    Here's what I came up with. I'm doing this on OS X, which doesn't have readlink -f, so I had to use a helper function to replace it. If you have it a proper readlink -f you can use that instead. Also, the use of while ... done < <(find ...) is not strictly needed in this case, a simple find ... | while ... done would work; but if you ever wanted to do something like set a variable inside the loop (like a count of matching files), the pipe version would fail because the while loop would run in a subshell. Finally, note that I use find ... -type l so the loop only executes on symlinks, not other types of files.

    # Helper function 'cause my system doesn't have readlink -f
    readlink-f() {
        orig_dir="$(pwd)"
        f="$1"
        while [[ -L "$f" ]]; do
            cd "$(dirname "$f")"
            f="$(readlink "$(basename "$f")")"
        done
        cd "$(dirname "$f")"
        printf "%s\n" "$(pwd)/$(basename "$f")"
        cd "$orig_dir"
    }
    
    target_file="$(readlink-f "$target_file")" # make sure target is normalized
    
    while IFS= read -d '' linkfile; do
        if [[ "$(readlink-f "$linkfile")" == "$target_file" ]]; then 
            printf "%s\n" "$linkfile"
        fi
    done < <(find "$search_dir" -type l -print0)
    
    0 讨论(0)
  • 2020-12-04 12:02

    Using GNU find, this will find the files that are hard linked or symlinked to a file:

    find -L /dir/to/start -samefile /tmp/orig.file
    
    0 讨论(0)
提交回复
热议问题