디렉토리 구조를 유지하면서 여러 기호 링크 생성

디렉토리 구조를 유지하면서 여러 기호 링크 생성

디렉토리 구조를 유지하면서 여러 폴더에서 심볼릭 링크를 생성하고 싶습니다. 몇 가지 답변을 읽었으며 이제 제가 생각할 수 있는 최선의 답변은 다음과 같습니다.

find /data/DIV5/SASC/e042_ctcl/input/*/Clean_data/*/*/*.fq.gz -type f -exec ln -sf \{\} . \;

이는 동일한 디렉토리에 모든 심볼릭 링크를 생성합니다. 하지만 내가 원하는 것은 find명령과 동일한 디렉터리 구조를 갖고 , 가능하다면 입력과 동일한 구조를 사용하는 것입니다. 예를 들어:input/*/Clean_data/*/*/*.fq.gz

파일과 디렉터리가 일치하는 경우 기호 링크는 명령을 사용하여 찾은 절대 링크와 동일한 구조를 따라야 합니다 find.

어떤 의견이라도 감사하겠습니다.

답변1

보기 흉하고 취약하지만 작업을 완료해야 합니다.

find /data/DIV5/SASC/e042_ctcl/input/*/Clean_data/*/*/*.fq.gz -type f -print0 | \
  xargs -0 -n 1 \
    sh -c 'mkdir -p "$PWD/`dirname $0`"; ln -s "$0" "$PWD/`dirname $0`"'

에서 영감을 받다카오스 답변, 나는 이 대안을 생각해 냈는데, 그것도불필요한 디렉토리 정리:

find /data/DIV5/SASC/e042_ctcl/input/*/Clean_data/*/*/*.fq.gz -type f   \
     -printf 'mkdir -p "${PWD}/%h"; ln -s "%p" \\\n\t"${PWD}/%h"\n'   | \
sed 's#/data/DIV5/SASC/e042_ctcl##'                                   | \
sh -

그것은 필요한 것을 생성합니다목차그리고왜냐하면주문하다:

mkdir -p "${PWD}//data/DIV5/SASC/e042_ctcl/input/x/Clean_data/0/a"; ln -s "/data/DIV5/SASC/e042_ctcl/input/x/Clean_data/0/a/foobar.fq.gz" \
    "${PWD}//data/DIV5/SASC/e042_ctcl/input/x/Clean_data/0/a"

그런 다음 원치 않는 디렉토리를 제거합니다.sed, 다음으로 이어집니다.

mkdir -p "${PWD}//input/x/Clean_data/0/a"; ln -s "/data/DIV5/SASC/e042_ctcl/input/x/Clean_data/0/a/foobar.fq.gz" \
    "${PWD}//input/x/Clean_data/0/a"

이것왜냐하면명령은 같은 줄에서 시작됩니다.목차대상을 자르는 동안 소스를 그대로 유지하려면 다음 줄을 계속 진행하세요. 동일한 라인에 인쇄하거나 별도의 라인에 인쇄하려면 더 정교한 작업이 필요합니다.sed스크립트.

설명은 다음과 같습니다.문서~을 위한찾다,매개변수 -printf:

%p 파일 이름(절대 경로 이름이 아니라 find에서 발견한 파일 이름, 즉 시작점 중 하나의 상대 경로).

%h 파일 이름의 선행 디렉터리(마지막 요소와 선행 슬래시를 제외한 모든 요소) 파일 이름에 슬래시가 포함되어 있지 않으면(예를 들어 명령줄에서 이름이 지정되었고 현재 작업 디렉터리에 있기 때문에) "%h"는 "."으로 확장됩니다. 이렇게 하면 "%h/%f"가 "/foo"로 확장되는 것을 방지할 수 있는데, 이는 놀랍고 아마도 바람직하지 않을 것입니다.

답변2

awk명령을 생성 한 후 다음으로 파이프해야 합니다 bash.

find /data/DIV5/SASC/e042_ctcl/input/*/Clean_data/*/*/*.fq.gz -type f | \
awk '{printf "mkdir -p `dirname %s`\nln -s %s ./%s \n", substr($0, 27), $0, substr($0, 27)}'

이렇게 하면 먼저 제어한 다음 마지막으로 파이프하는 명령 목록이 생성됩니다 bash. 전체 명령은 다음과 같습니다.

find /data/DIV5/SASC/e042_ctcl/input/*/Clean_data/*/*/*.fq.gz -type f | \
awk '{printf "mkdir -p `dirname %s`\nln -s %s ./%s \n", substr($0, 27), $0, substr($0, 27)}' | bash

답변3

내 인상은 당신이 이와 같은 도구를 찾고 있다는 것입니다GNU 스토우.

GNU Stow는 파일 시스템의 서로 다른 디렉터리에 있는 다양한 소프트웨어 및/또는 패키지를 가져와 동일한 위치에 설치된 것처럼 보이게 만드는 심볼릭 링크 팜 관리자입니다. 예를 들어 /usr/local/binetc.의 파일에 대한 심볼릭 링크를 포함할 수 있으며 /usr/local/stow/emacs/bin, 마찬가지로 등 /usr/local/stow/perl/bin의 다른 하위 디렉터리도 재귀적으로 포함할 수 있습니다 .../share..../man

사용 사례와 일치하는지 확인하세요.

답변4

zsh에는 편리한 기능이 있습니다zmv. 먼저 로드합니다( .zshrc단일 세션 사용을 위해 명령줄에서 또는 명령줄에서 이 작업을 수행할 수 있음).

autoload -U zmv
alias zcp='zmv -C'
alias zln='zmv -L'

심볼릭 링크 포리스트를 다시 만드는 방법은 다음과 같이 간단합니다.

 zln -s '/data/DIV5/SASC/e042_ctcl/(input/*/Clean_data/*/*/*.fq.gz)' '$1'

Clean_data두 수준 깊이가 아닌 디렉터리를 재귀적으로 탐색 하려는 경우 :

 zln -s '/data/DIV5/SASC/e042_ctcl/(input/*/Clean_data/**/*.fq.gz)' '$1'

한 가지 큰 제한 사항이 있습니다. 이는 필요한 하위 디렉터리를 생성하지 않는다는 것입니다. 필요 에 따라 디렉터리를 생성하기 위해 래퍼 함수를 ​​정의하고 사용하여 ln이를 수행합니다 .

ln_s_mkdir () {
  mkdir -p -- ${(P)#}
  ln -s "$@"
}
 zmv -p ln_s_mkdir '/data/DIV5/SASC/e042_ctcl/(input/*/Clean_data/**/*.fq.gz)' '$1'

zsh를 사용하여 명령을 좀 더 빠르게 실행할 수 있습니다.내부 mkdirln명령(대부분의 시스템에 있는 GNU 유틸리티보다 옵션이 적기 때문에 기본적으로 로드되지 않습니다.)

zmodload -F zsh/files b:zf_ln b:zf_mkdir
ln_s_mkdir () {
  zf_mkdir -p -- ${(P)#}
  zf_ln -s "$@"
}
 zmv -p ln_s_mkdir '/data/DIV5/SASC/e042_ctcl/(input/*/Clean_data/**/*.fq.gz)' '$1'

관련 정보