파일 목록을 대상 인덱스와 일치시켜 이동합니다.

파일 목록을 대상 인덱스와 일치시켜 이동합니다.

파일 이름 목록(일부는 공백 포함)을 포함하고, 해당 파일이 속한 전체 파일 경로 목록(공백 포함)을 무작위 순서로 포함하는 두 개의 텍스트 파일 src.txt및 가 있다고 가정해 보겠습니다 . 예를 들어:dest.txtsrc.txt/src/dir/dest.txt

src.txt:

file 1.jpg
file_2.html
file 3.jpg

타겟.txt:

/dest/dir 1/file 3.jpg
/dest/file4.txt
/dest/file 5.txt
/dest/dir 2/file 1.jpg
/dest/file_2.html

쉘에서 대량 이동 작업을 수행하는 방법은 무엇입니까? 소스 파일을 반복 하면서 while read해당 명령을 사용해야 한다고 확신 하지만 여기서는 이것이 필수 인지 필수 mv인지 잘 모르겠습니다 . 공백 문자 구문 분석 오류가 계속 발생합니다 .grepsedcannot stat...

답변1

그리고 zsh:

src=(${(f)"$(<src.txt)"})
for f (${(f)"$(<dest.txt)"})
(($src[(Ie)$f:t])) && mv /src/dir/$f:t $f

이는 배열의 각 파일을 읽은 다음 배열의 각 요소를 읽습니다."목적지"basename( 모든 선행 경로 이름 구성 요소를 제거하는 수정자)이 다음 :t인 경우 배열zsh"원천"배열한 다음 파일을 이동합니다. 연습 실행을 수행하려면 mv로 바꾸십시오 printf '"%s" -> "%s"\n'.


이제 다음을 실행할 수도 있습니다(여전히 zsh).

for f (${(f)"$(grep -Ff src.txt dest.txt)"})
mv /src/dir/$f:t $f

src.txtin의 파일 이름이 경로 목록의 디렉터리 이름(또는 해당 이름의 일부)과 일치하지 않는 in의 파일 이름 및 in과 같은 경로는dest.txt(예:한data1src.txt/path/data1_dir/some_filedest.txtgrep/filename$Fdest.txtsrc.txtbash4

readarray -t files < <(sed 's|[[\.*^$/]|\\&|g;s|.*|/&$|' src.txt | grep -f- dest.txt)
for f in "${files[@]}"; do mv /src/dir/"${f##*/}" "$f"; done

답변2

줄 바꿈이 허용되는 구분 기호인 경우 POSIX 셸에서 다음이 안정적으로 작동해야 합니다.

IFS='
';set -f
for   f in $(cat <"$destfile")
do    [ -e "./${f##*/}" ] ||
      [ -h "./${f##*/}" ] &&
      mv   "./${f##*/}"  "$f"
done

이 솔루션에는 두 가지 가능한 문제가 있을 수 있습니다.

  • 입력 파일 크기가 너무 커서 이렇게 한 번에 분할할 수 없습니다.

    • 내 시스템에서는 입력이 수만 줄에 도달할 때까지 이것은 전혀 심각하게 고려할 가치가 없습니다.
  • 파일 이름은 $destfile현재 디렉터리에 있을 수 있지만아니요무슨 일이 있어도 감동받을 것입니다.

    • 이 솔루션은 두 입력 파일 비교를 완전히 포기하고 $destfile현재 디렉터리에 있는 각 마지막 경로 이름 구성 요소의 존재 여부만 확인하므로, 의도하지 않게 일치할 수 있는 파일 이름은 고려해서는 안 됩니다.

첫 번째 문제만 처리해야 하는 경우:

sed -ne"s|'|'"'\\&&|g' <"$destfile"    \
    -e "s|.*/\([^/].*\)|_mv './\1' '&'|p" | 
sh  -c '_mv(){ [ -e "$1" ]||[ -h "$1" ]&& mv "$@";};. /dev/fd/0'

그렇다면 마지막에 제거하고 다음을 사용할 sh수 있습니다 .dash. /dev/fd/0

sed ... | sh -cs '_mv(){ ...;}'

... dash이상하게도 아무런 불만 없이 명령줄과 표준 입력 호출 옵션을 모두 처리하기 때문입니다. 이식성이 좋지는 않지만 . /dev/fd/0이식성이 뛰어나기는 하지만 표준을 엄격하게 준수하지도 않습니다.

두 번째 질문이 질문인 경우:

export  LC_ALL=C 
sed  -ne'\|/$|!s|.*/\(.*\)|\1/&|p' <"$destfile" |
sort -t/ -k1,1 - ./"$srcfile"  |  cut  -d/ -f2- |
sed  -e "\|/|!N;\|\n.*/|!d"    \
     -e "s|'|'"'\\&&|g'        \
     -e "s|\n|' '|;s|.*|mv './&'|" | sh

...모든 파일 이름이 . ./"$srcfile"에 있는 한 두 개의 동일한 비교 중 짧은 항목이 맨 위에 표시되므로 첫 번째 필드만 중요하고 파일 이름이 각 경로 이름의 시작 부분에 추가되면 두 항목의 병합 작업이 수행됩니다. 파일은 다음 순서를 출력합니다."$destfile"sort"$destfile"sort

$srcfile:  no /
$destfile: match
$destfile: unique
$destfile: unique
...
$srcfile:  no /
$destfile: match
$destfile: unique

...따라서 일치하지 않는 줄로 시작하는 줄 쌍에만 신경 쓰면 됩니다 /.

답변3

while read i; do echo cp \""$i"\" \"$(grep "/$i$" dst.txt)\"; done < src.txt

그러면 의도한 내용이 인쇄됩니다. echo실제로 파일을 복사하려면 삭제하세요 .

답변4

스크립트 줄은 스크립트를 생성하고 스크립트를 생성합니다.

이 예에서는 sedon 에 대한 첫 번째 호출을 사용하여 파일 복사를 위한 쉘 스크립트를 생성하기 위해 실행될 src.txt두 번째 스크립트를 생성 합니다.seddest.txt

다음 줄은 다음과 같습니다.

$ sed -n "$(sed 's,\(..*\),/\\/\1$/ { s/^/cp "\1" "/; s/$/";/; p; },' src.txt)" dest.txt #| sh -x

그리고 출력:

cp "file 3.jpg" "/dest/dir 1/file 3.jpg";
cp "file 1.jpg" "/dest/dir 2/file 1.jpg";
cp "file_2.html" "/dest/file_2.html";

#| sh명령 끝에 있는 주석을 참고하십시오. 이렇게 하면 명령을 시도해보고 그 내용을 확인할 수 있으며, 제대로 작동하면 파이프의 주석 처리를 해제 sh하고 실제로 파일을 복사할 수 있습니다.

내부 sed 명령은 src.txt를 기반으로 sed 스크립트를 작성합니다. 생성된 스크립트의 첫 번째 줄은 다음과 같습니다.

/\/file 1.jpg$/ { s/^/cp file 1.jpg /; p; }

작동 방식은 다음과 같습니다.

입력하다:

    $ cat src.txt
    file 1.jpg
    file_2.html
    file 3.jpg

    $ cat dest.txt
    /dest/dir 1/file 3.jpg
    /dest/file4.txt
    /dest/file 5.txt
    /dest/dir 2/file 1.jpg
    /dest/file_2.html

첫 번째 sed전화. 이는 두 번째 호출에 의해 해석될 생성된 스크립트를 보여줍니다 sed.

$ sed 's,\(..*\),/\\/\1$/ { s/^/cp "\1" "/; s/$/";/; p; },' src.txt
/\/file 1.jpg$/ { s/^/cp "file 1.jpg" "/; s/$/";/; p; }
/\/file_2.html$/ { s/^/cp "file_2.html" "/; s/$/";/; p; }
/\/file 3.jpg$/ { s/^/cp "file 3.jpg" "/; s/$/";/; p; }

첫 번째 명령의 출력을 sed두 번째 호출에 전달되는 명령줄의 스크립트 로 사용하려면 셸 명령 대체를 사용합니다 sed.

$ sed -n "$(sed 's,\(..*\),/\\/\1$/ { s/^/cp "\1" "/; s/$/";/; p; },' src.txt)" dest.txt
cp "file 3.jpg" "/dest/dir 1/file 3.jpg";
cp "file 1.jpg" "/dest/dir 2/file 1.jpg";
cp "file_2.html" "/dest/file_2.html";

sh -x이제 xtrace 옵션( )을 사용하여 sed의 출력을 셸로 파이프합니다. 파일이 없어서 오류가 발생합니다.

$ sed -n "$(sed 's,\(..*\),/\\/\1$/ { s/^/cp "\1" "/; s/$/";/; p; },' src.txt)" dest.txt  | sh -x
+ cp file 3.jpg /dest/dir 1/file 3.jpg
cp: cannot stat ‘file 3.jpg’: No such file or directory
+ cp file 1.jpg /dest/dir 2/file 1.jpg
cp: cannot stat ‘file 1.jpg’: No such file or directory
+ cp file_2.html /dest/file_2.html
cp: cannot stat ‘file_2.html’: No such file or directory

관련 정보