
답변1
논증은 매우 강력한 대체 표현을 --xform
원하는 만큼 취합니다 . sed
귀하의 경우 마지막까지 모든 것과 일치하는 패턴을 사용 /
하고 아무것도 바꾸지 마십시오.
tar cvf allfiles.tar --xform='s|.*/||' $(<mylist.txt)
--show-transformed-names
새 이름을 보려면 추가하세요 .
이 대체는 명령줄에 제공된 파일 이름뿐만 아니라 모든 파일 이름에 적용됩니다. 예를 들어 파일이 있고 /a/b/c
목록에 가 지정되어 있는 경우 /a
최종 파일 이름은 가 c
아니라 입니다 b/c
. 예를 들어 귀하의 경우에는 항상 더 명확하고 정확한 대체 목록을 제공할 수 있습니다.
--xform='s|^tmp/path2/||;s|^tmp/||;s|^path3/||'
이니셜은 /
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