`find` *output* 파일 이름에서 모든 심볼릭 링크를 효율적으로 역참조하는 방법은 무엇입니까?

`find` *output* 파일 이름에서 모든 심볼릭 링크를 효율적으로 역참조하는 방법은 무엇입니까?

완전히 확인되고 지정된 디렉토리에 상대적인 경로가 필요합니다. 일반적으로 경로 수가 100,000개보다 크므로 이 작업은 효율적으로 수행되어야 합니다.

상태:다음 내용이 포함된 디렉터리가 있습니다.최대다음과 같은 다른 디렉토리에 대한 심볼릭 링크

foo
 123 -> ../baz/123
 896 -> ../bar/896

(foo에는 디렉토리에 대한 심볼릭 링크가 포함될 뿐만 아니라 캡처해야 하는 일반 파일도 포함되어 있습니다.)

이러한 기호 링크 디렉토리에는 파일이 포함되어 있습니다. 이 파일 목록을 다음 형식으로 얻고 싶습니다.

baz/123/some.file
bar/123/other.file

즉, "find"가 심볼릭 링크를 찾으면 경로를 역참조하고 싶습니다.콘텐츠를 보고할 때.

그래서 foo의 상위 디렉터리에서 다음 명령을 실행합니다.

find -L foo -type f

그러나 이것은 작동하지 않습니다.

-L솔직히 말해서 이 동작을 달성하려면 "심볼릭 링크를 따르라"고 주장하는 옵션이 필요할 것입니다 . 그러나 그실제행동하는 것은 보는 것이다입력하다이러한 디렉터리의 내용은 그 안에 있는 파일과 역참조되지 않은 이름을 보고합니다. 결과는 다음과 같습니다.

foo/baz/123/some.file
foo/bar/896/another.file

결과는 파일 경로 목록을 모든 항목으로 설정하는 데 사용됩니다.완전히 해결됨그리고 2.foo의 상위 디렉토리에 상대적이므로 각 결과도 이 기준을 충족해야 합니다. 이러한 목적을 위해 모든 링크를 확인할 수 있음을 보장할 수 있습니다. 둥글거나 지나치게 깊은 것은 없습니다. 전부는 아니지만 대부분의 링크는 파일이 아닌 디렉터리를 가리킵니다.

현재 제가 할 수 있는 최선의 방법은 Python 스크립트를 사용하여 참조되지 않은 모든 경로를 확인된 경로로 다시 작성하는 것입니다. 하지만 관련 문서의 양이 많기 때문에100000+이는 그다지 실용적이지 않습니다. (그리고 오히려 우스꽝스럽습니다. find이미 역참조하는 문제가 발생했기 때문에 역참조된 경로를 반환하지 않습니다.) (편집: 이 게시물에 대한 내 의견을 참조하세요. 해결책이 아닌 것을 찾았습니다(작업을 효과적으로 수행하지만 잘못된 방식으로 외부 명령을 실행하기 때문입니다).

나는 외부 명령만 사용하여 이 작업을 수행할 수 있어야 한다고 확신 하지만 여기서는 올바른 동작이 없으며 명백한 이유로 배제 되는 find매뉴얼 페이지를 찾지 못했습니다 . 내부 명령이 아닙니다 . 어떤 아이디어가 있나요?-L-H-P-follow-printf %l-execfind

편집 2: 이 시점에서 Stephen은 당신이 찾아야 할 특별한 이유가 없다고 나에게 확신시켰습니다.회의이 기능은 내부적으로 존재하므로 합리적으로 유효한 답변을 얻을 수 있습니다.

답변1

find일반적으로 귀하가 요구하는 내용은 그다지 의미가 없으므로 규정이 없다는 것은 놀라운 일이 아닙니다.

상대 대상이 있는 기호 링크는 기호 링크의 경로를 기준으로 합니다. 예를 들어, 심볼릭 링크를 따라 디렉터리를 탐색하다가 상대 또는 절대 심볼릭 링크(또는 심볼릭 링크 구성 요소가 있는 경로가 있는 심볼릭 링크) 인 , , 및 을 find발견하는 경우 어떻게 해야 합니까?a/b/c/daa/ba/b/c

다음으로 확장되는 find술어나 GNU 지시어를 찾고 있다면-printf %현재 디렉터리에 대한 상대 파일 경로 또는 임의 디렉터리에 대한 기호화되지 않은 링크, 난 두려워하지.

Linux를 사용하는 경우 다음을 사용하여 이러한 파일의 절대 경로를 얻을 수 있습니다.

find -L foo -type f -exec readlink -f {} \;

realpath발견한 대로 여러 경로 인수를 허용하는 명령이 하나 이상 있으며 , -exec cmd {} +표준 구문과 결합하면 실제 경로 명령을 가능한 한 적게 실행하므로 더 효율적입니다.

find -L foo -type f -exec realpath {} +

find -L foo -type f -print0 | xargs -r0 realpath

realpath여러 명령이 필요한 것처럼 더 빠를 수도 있습니다. find첫 번째 명령이 작동하기 시작하는 동안 더 많은 파일을 계속 찾을 수 있으므로 realpath단일 프로세서 시스템에서도 효율성이 향상될 수 있습니다.

-print0표준은 아니며 xargs -r0GNU에서 유래했지만 다른 많은 구현(예: 대부분의 최신 BSD)에서 발견됩니다.

Zsh에는 이를 지원하는 기능이 내장되어 있습니다.

print -rl foo/***/*(-.:A)

정렬 순서가 중요하지 않은 경우 다음을 수행하여 정렬을 비활성화하고 효율성을 높일 수 있습니다.

print -rl foo/***/*(-.oN:A)

현재 디렉토리에 대한 상대 경로로 변환하려면 다음을 참조하십시오.그래서 질문은.

이러한 모든 파일이 현재 디렉터리 내에 절대 표준 경로를 가지고 있다는 것을 알고 있는 경우(해당 구성 요소 중 어느 것도 심볼릭 링크가 아님) 다음과 같이 단순화할 수 있습니다(계속 사용 zsh).

files=(foo/***/*(-.:A))
print -rl -- ${files#$PWD/}

짧고 편리하며 파일 이름에 포함된 모든 문자에서 작동하지만 find+보다 빠를 지는 의문입니다 realpath.

Debian realpath및 GNU 도구를 사용하면 다음을 수행할 수 있습니다.

cd -P .
find -L foo -type f -exec realpath -z {} + | 
  gawk -v p="$PWD" -v l="${#PWD}" -v RS='\0' -vORS='\0' '
    substr($0, 1, l+1) == p "/" {$0 = substr($0, l+2)}; 1' |
  xargs -r0 whatever you want to do with them

이제 귀하가 찾고 있는 기능을 갖춘 최신 버전의 GNU coreutils가 있다는 것을 깨달았으므로 realpath이것은 단지 질문일 뿐입니다.

find -L foo -type f -print0 |
  xargs -r0 realpath -z --relative-base . |
  xargs -r0 whatever you want to do with them

(상대 경로를 원하는 경우 심볼릭 링크 자유 경로가 현재 작업 디렉토리 아래에 있지 않은 파일이라도 --relative-to .대신 사용하십시오.)--relative-base .

답변2

ls -1 -R --unreference 화장실 -l |

나를 위해 그랬어요. 하지만 파일 수를 세고 심볼릭 링크의 대상까지 재귀적으로 파헤치기만 하면 됩니다. 나는 그들에게 보여줄 필요가 없습니다. 하지만 그렇게 했으므로 파이프와 단어 수만 제거하면 다음과 같이 간단해집니다.

ls -1 -R --역참조

관련 정보