이름이 문자열로 시작하는 모든 파일을 목록에서 이동하는 방법은 무엇입니까?

이름이 문자열로 시작하는 모든 파일을 목록에서 이동하는 방법은 무엇입니까?

strings.txt문자열 목록이 포함된 파일이 있습니다.

GCA_001677475.1
GCA_003410275.1
GCA_002310615.1
GCA_000007405.1
GCA_000219515.3

내 디렉토리에 다음 이름을 가진 파일이 많이 있습니다.

GCA_000005845.2_ASM584v2_protein.faa
GCA_000006925.2_ASM692v2_protein.faa
GCA_000007405.1_ASM740v1_protein.faa
GCA_000007445.1_ASM744v1_protein.faa
GCA_000008865.2_ASM886v2_protein.faa
GCA_000009565.2_ASM956v1_protein.faa

그 이름을 로 옮기면 됩니다 . 지금까지 다음 과 같이 strings.txt사용해 보았습니다 .xargsmv

cat strings.txt | xargs -I % mv %*faa ./Data

그러나 그것을 정규식으로 취급 mv하지 않고 %*faa정확한 이름을 가진 파일을 찾으려고 시도합니다(물론 아무것도 찾지 못합니다). 나는 또한 사용해 보았지만 ls같은 방식으로 작동합니다.

cat strings.txt | xargs -I {} ls {}*faa

그럼 어떻게 해야 하나요?

답변1

xargs bash -O nullglob -c '
    for prefix do
        set -- "$prefix"*.faa
        [ "$#" -gt 0 ] && mv -- "$@" ./Data
    done' sh <strings.txt

이는 인라인 스크립트 에 xargs일괄적으로 문자열을 공급하는 데 사용됩니다 .strings.txtbash

각 문자열에 대해 인라인 스크립트는 현재 디렉터리에 해당 문자열( 패턴을 만들기 위해 끝에 bash추가됨)과 일치하는 파일 이름이 있는지 여부를 테스트하고 , 그렇다면 해당 파일이 이미 존재한다고 가정하여 해당 디렉터리로 이동합니다.*.faaData

인라인 스크립트에 대한 셸 옵션을 설정하여 nullglob구성된 패턴이아니요무엇이든 일치하면 패턴이 제거됩니다(확장되지 않은 채로 남아 있는 것이 아님).

귀하의 예에 있는 일부 문자열이 귀하가 표시한 파일 이름과 일치하지 않기 때문에 패턴 일치를 명시적으로 테스트하고 있습니다. 이는 위치 인수 목록을 전역 확장 결과로 설정한 다음 목록의 길이( )가 0보다 큰지 테스트하여 $#수행 됩니다.

분명히 다음과 같이 대신 이 작업을 수행할 수도 있습니다 xargs.

shopt -s nullglob

while IFS= read -r prefix; do
    set -- "$prefix"*.faa
    [ "$#" -gt 0 ] && mv -- "$@" ./Data
done <strings.txt

이것은 여전히실패하다접두사 문자열 중 하나가 수천 개의 파일 이름과 일치하는 경우( mv명령줄이 너무 길어집니다). 이 경우에는 다음을 사용할 수 있습니다.

shopt -s nullglob

while IFS= read -r prefix; do
    set -- "$prefix"*.faa
    if [ "$#" -gt 0 ]; then
        printf '%s\n' "$@" | xargs sh -c 'mv -- "$@" ./Data' sh
    fi
done <strings.txt

이는 접두사 문자열이나 파일 이름에 개행 문자가 포함되어 있지 않다고 가정합니다.

답변2

가능한 해결책은 다음과 같습니다.

cat strings.txt | xargs -I '%' find . -type f -name "%*" -exec mv -t your_path {} +

터치한 GCA_000007405.1_ASM740v1_protein.faa것이 유일한 일치 항목입니다.

답변3

필요도 없고 xargs복잡한 것도 없습니다. 모든 파일이 동일한 디렉터리에 있는 경우 다음을 수행하면 충분합니다.

$ while read string; do 
    mv "$string"_* ./Data; 
  done < strings.txt 

또는 이름이 로 시작 -하거나 다른 이상한 문자가 포함된 경우 다음을 사용하세요.

$ while read -r string; do 
    mv -- "$string"_* ./Data; 
  done < strings.txt 

답변4

빠르고 더러운 해킹:cat strings.txt| xargs -i sh -c 'mv {}* your/path/'>&/dev/null

더 적은 수의 올바른 해킹:export dir=$(ls -1); cat strings.txt| xargs -i sh -c 'grep "^{}" <<<$dir && mv {}* your/path'; dir=""

관련 정보