답변1
이 매개변수는 매우 강력한 대체 표현식을 --xform
원하는 만큼 취합니다 . sed
귀하의 경우 끝까지 모든 것과 일치하는 패턴을 사용한 /
다음 무엇이든 바꾸십시오.
tar cvf allfiles.tar --xform='s|.*/||' $(<mylist.txt)
--show-transformed-names
새 이름을 보려면 추가하세요 .
이 대체는 명령줄에 지정된 파일 이름뿐만 아니라 모든 파일 이름에 적용됩니다. 따라서 예를 들어 파일이 하나 있고 /a/b/c
목록에 만 지정되어 있는 경우 /a
최종 파일 이름은 that c
이 아니라 that 입니다 b/c
. 귀하의 경우와 같이 언제든지 더 명확하고 정확한 대체 목록을 제공할 수 있습니다.
--xform='s|^tmp/path2/||;s|^tmp/||;s|^path3/||'
첫 번째 문자는 /
tar에 의해 제거되므로(tar를 사용하지 않는 한 -P
) 위의 표현식에서는 해당 문자가 손실됩니다. 또한 가장 긴 일치 항목이 먼저 수행되도록 디렉터리 목록을 정렬해야 합니다. 그렇지 않으면 제거되었기 tmp/path2/
때문에 일치 항목이 없습니다 . tmp/
하지만 다음과 같이 이 목록을 자동으로 만들 수 있습니다.
--xform="$(sed <mylist.txt 's|[^/]*$||; s|^/||; s:.*:s|^&||;:' | sort | tr -d '\n')"
답변2
GNU를 사용하면 언제 어디서나 사용할 tar
수 있으며 즉시 작동합니다.-C
$ tree
.
├── 1
│ └── aaa
├── 2
│ └── bbb
└── 3
└── ccc
# Caveat: the directory change is always relative to directory tar is using *at
# that time*, so the following doesn't work:
$ tar -cf foo.tar -C 1 aaa -C 2 bbb -C 3 ccc
tar: 2: Cannot open: No such file or directory
tar: Error is not recoverable: exiting now
$ tar -cf foo.tar -C 1 aaa -C ../2 bbb -C ../3 ccc
$ tar tf foo.tar
aaa
bbb
ccc
# You can avoid the special case for the first directory by always specifying
# an absolute path:
$ tar -cf foo.tar -C $(pwd)/1 aaa -C $(pwd)/2 bbb -C $(pwd)/3 ccc
# Now let's create that automatically from your file:
$ cat mylist.txt
/tmp/1/aaa
/tmp/2/bbb
/tmp/3/ccc
$ while read -r line; do printf '-C %s %s ' $(dirname "$line") $(basename "$line") ; done < mylist.txt
-C /tmp/1 aaa -C /tmp/2 bbb -C /tmp/3 ccc
# That looks about right. Let's use it in our tar command:
$ tar -cvf foo.tar $(while read -r line; do printf '-C %s %s ' $(dirname "$line") $(basename "$line") ; done < mylist.txt)
aaa
bbb
ccc