tar 아카이브에서 디렉토리 이름을 바꿀 수 있습니까? 내 사용 사례는 특정 디렉토리 구조를 가진 tarball을 가정하는 외부 제공 RPM 사양 파일이 있고 최상위 디렉토리 이름이 사양 파일에서 예상하는 것과 일치하지 않는 외부 제공 tarball이 있다는 것입니다. 나는 tarball이나 RPM 사양 파일을 생성하는 스크립트를 제어할 수 없으므로 둘 중 하나를 다른 것과 일치하도록 변경할 수 없습니다.
제가 하고 있는 것은 압축을 풀고 디렉토리 이름을 변경한 후 새로운 타르볼을 생성하는 것인데, 이것을 할 수 있는 다른 방법이 있는지 궁금합니다.
답변1
파일 이름이 고정 크기(100바이트) 필드에 저장되는 이전 형식과 호환되는 아카이브의 경우 이는 그리 어렵지 않을 것입니다. 그러나 tar 내부에서 파일 이름을 바꿀 수 있는 도구는 알지 못합니다. 보관소. 또한 압축된 아카이브의 경우 어쨌든 새 파일을 생성해야 합니다.
더 쉬울 것 같지만 실행 중에 아카이브를 필터링하고 파일 이름을 바꿀 수 있는 기존 도구는 없습니다. 스크립팅 언어의 tar 라이브러리 위에 하나를 구축할 수 있습니다. 예를 들어 다음은 tar 아카이브에서 디렉터리 이름을 바꾸는 개념 증명 스크립트입니다.펄과Archive::Tar
. 아카이브는 메모리에 완전히 로드됩니다. 이는 본질적인 제한 사항입니다 Archive::Tar
.
#!/usr/bin/env perl
## Usage: tar-rename OLDPREFIX NEWPREFIX
use strict;
use warnings;
use Archive::Tar;
my ($from, $to) = @ARGV;
my $tar = Archive::Tar->new(\*STDIN);
foreach my $file ($tar->get_files()) {
my $name = $file->name;
$name =~ s~\A\Q$from\E($|/)~$to$1~;
$file->rename($name) unless $name eq $file->name;
}
$tar->write(\*STDOUT);
GNU tar에는 멤버 이름을 동적으로 바꾸는 기능이 없지만pax
(POSIX cpio
및 대안 tar
) 실제로. 그러나 pax
아카이브에서 동시에 읽고 쓸 수는 없습니다. 당신이 할 수 있는 일은 아카이브를 일반 트리로 노출하는 것입니다.AVFS을 클릭하고 새 아카이브를 만듭니다 pax
. 이렇게 하면 파일 이름(변환된 이름 제외), 내용, 시간 및 모드가 유지되지만 파일 소유권은 다시 사용자에게 재설정됩니다(루트로 실행하지 않는 한).
mountavfs
cd "~/.avfs$PWD/old.tgz#"
pax -w -s '!bar!baz!' -s '!bar/!baz/' . | gzip >new.tgz
답변2
sr_의 hack과 Gilles의 대답은 모두 좋아 보이지만 문제가 대상 tarball의 루트 디렉터리 이름일 뿐이라면 다른 해결책은 %setup
rpmbuild를 실행할 때 필요한 디렉터리 이름 바꾸기를 수행하도록 매크로를 재정의하는 것일 수 있습니다.
다음과 같은 것입니다(특히 올바른 압축 해제 도구를 교체하고 사용하여 old-dir
실제 구성에 맞게 조정하고 개선해야 합니다 ) .desired-dir
~/.rpmmacros
%setup cd ../BUILD \
rm -rf cd-player \
bunzip2 -dc ../SOURCES/%{name}-%{version}.tar.bz2 | tar -xvvf - \
if [ $? -ne 0 ]; then \
exit $? \
fi \
mv <old-dir> <desired-dir> \
cd <desired-dir> \
cd ../BUILD/cd-player \
chmod -R a+rX,g-w,o-w .
솔직히, 가장 이국적인 상황이 아니라면 이 작업을 수행하지 않겠지만 귀하의 경우는 그럴 수도 있습니다. :)
답변3
다른 곳에서 정답을 찾으려면 이 페이지를 확인하세요.
http://www.rpm.org/max-rpm/s1-rpm-inside-macros.html
이는 %setup 매크로에 -n을 전달하여 rpmbuild에 tarball의 최상위 폴더 이름을 알릴 수 있음을 의미합니다.
답변4
이 기사는 내가 필요한 것과 꽤 비슷하지만 시가는 없습니다. Archive::Tar 내부의 이름 바꾸기 기능으로 인해 내 폴더가 엉망이 되었습니다. 파일에는 잘 작동하지만 폴더는 후행 슬래시(/) 없이 나옵니다. 예:
앞으로
$VAR1 = [
'old_root_folder/',
'old_root_folder/.dockerignore',
'old_root_folder/.github/',
.....
뒤쪽에
$VAR1 = [
'newrootfolder',
'newrootfolder/.dockerignore',
'newrootfolder/.github/',
......
루트 폴더는 더 이상 슬래시로 지정되지 않습니다. 그것은 중요하지 않은 것으로 밝혀졌습니다. 새 아카이브는 정상적으로 추출될 수 있으며 폴더는 슬래시로 끝나지 않습니다.
나는 다음 Perl 조각으로 끝났습니다.
sub renameRootFolderInTar
{
my $file = shift;
my $new_root_folder_name = shift;
my $tar = Archive::Tar->new($file);
my @files_in_archive = $tar->list_files;
my $root_folder = @files_in_archive[0]; # whatever they named the root folder in the archive
$root_folder =~ s/\/$//g;
foreach(@files_in_archive)
{
my $this_archive_file = $_;
my $dest = $this_archive_file;
$dest =~ s/^$root_folder\/(.*)/$new_root_folder_name\/$1/g;
$tar->rename($this_archive_file,$dest);
}
my $success = $tar->write( "renamed.tar.gz", COMPRESS_GZIP );
if($success)
{
unlink $file;
return "renamed.tar.gz";
}
else
{
print "Sorry, there was a problem when dealing with the raw archive $file:\n";
print "Could not save renamed.tar.gz\n";
exit;
}
}
물론 이는 아카이브의 첫 번째 항목이 폴더라고 가정합니다. 그러나 당신은 요점을 이해합니다.