كيف يمكنني القطران دليل الملفات والمجلدات دون إدراج الدليل نفسه؟
سؤال
أنا عادة ما تفعل:
tar -czvf my_directory.tar.gz my_directory
ماذا لو كنت أريد فقط تضمين كل شيء (بما في ذلك أي ملفات نظام مخفية) في my_directory، ولكن ليس الدليل نفسه؟ أنا لا أريد:
my_directory
--- my_file
--- my_file
--- my_file
أريد:
my_file
my_file
my_file
المحلول
cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd -
يجب القيام بهذه المهمة في سطر واحد. يعمل بشكل جيد للملفات المخفية أيضا. "*" لا توسع الملفات المخفية عن طريق توسيع اسم المسار على الأقل في باش. أدناه هي تجربتي:
$ mkdir my_directory
$ touch my_directory/file1
$ touch my_directory/file2
$ touch my_directory/.hiddenfile1
$ touch my_directory/.hiddenfile2
$ cd my_directory/ && tar -zcvf ../my_dir.tgz . && cd ..
./
./file1
./file2
./.hiddenfile1
./.hiddenfile2
$ tar ztf my_dir.tgz
./
./file1
./file2
./.hiddenfile1
./.hiddenfile2
نصائح أخرى
استخدم ال -C
التبديل من القطران:
tar -czvf my_directory.tar.gz -C my_directory .
ال -C my_directory
يحكي القطران لتغيير الدليل الحالي ل my_directory
, ، وثم .
يعني "إضافة الدليل الحالي بأكمله" (بما في ذلك الملفات المخفية والدفعات الفرعية).
تأكد من أن تفعل -C my_directory
قبل أن تفعل .
وإلا فستحصل على الملفات في الدليل الحالي.
يمكنك أيضا إنشاء أرشيف كالمعتاد واستخراجه مع:
tar --strip-components 1 -xvf my_directory.tar.gz
القي نظرة على --transform
/--xform
, ، يمنحك الفرصة لتدليك اسم الملف مع إضافة الملف إلى الأرشيف:
% mkdir my_directory
% touch my_directory/file1
% touch my_directory/file2
% touch my_directory/.hiddenfile1
% touch my_directory/.hiddenfile2
% tar -v -c -f my_dir.tgz --xform='s,my_directory/,,' $(find my_directory -type f)
my_directory/file2
my_directory/.hiddenfile1
my_directory/.hiddenfile2
my_directory/file1
% tar -t -f my_dir.tgz
file2
.hiddenfile1
.hiddenfile2
file1
تحويل التعبير يشبه ذلك sed
, ، ويمكننا استخدام فواصل أخرى غير /
(,
في المثال أعلاه).
https://www.gnu.org/software/tar/manual/html_section/tar_52.html.
TL؛ دكتور
find /my/dir/ -printf "%P\n" | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -
مع بعض الشروط (أرشيف فقط الملفات، المؤسسات والإيمان):
find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -
تفسير
أدناه لسوء الحظ تتضمن دليل الوالدين ./
في الأرشيف:
tar -czf mydir.tgz -C /my/dir .
يمكنك نقل جميع الملفات من هذا الدليل باستخدام --transform
خيار التكوين، ولكن هذا لا يتخلص من .
دليل نفسه. يصبح من الصعب بشكل متزايد ترويض الأمر.
يمكنك استخدام $(find ...)
لإضافة قائمة ملف إلى الأمر (مثل في إجابة ماغنوس)، ولكن ذلك يحتمل أن يؤدي الخطأ "قائمة الملفات لفترة طويلة". أفضل طريقة هي الجمع بين القطران -T
الخيار، مثل هذا:
find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -
أساسا ما يفعله هو قائمة جميع الملفات (-type f
)، روابط (-type l
) والدلائل الفرعية (-type d
) تحت الدليل الخاص بك، جعل جميع أسماء الملفات نسبة -printf "%P\n"
, ، ثم اجتياز ذلك إلى أمر القطران (يأخذ أسماء الملفات من Stdin باستخدام -T -
). ال -C
هناك حاجة إلى الخيار حتى يعرف القطران حيث توجد الملفات ذات الأسماء النسبية. ال --no-recursion
العلم هو لذا فإن القطران لا ينص على مجلدات، يقال إلى الأرشفة (تسبب ملفات مكررة).
إذا كنت بحاجة إلى القيام بشيء خاص مع أسماء الملفات (تصفية، بعد التعايدات وغيرها)، find
الأمر قوي جدا، ويمكنك اختبارها عن طريق إزالة tar
جزء من الأمر أعلاه:
$ find /my/dir/ -printf "%P\n" -type f -o -type l -o -type d
> textfile.txt
> documentation.pdf
> subfolder2
> subfolder
> subfolder/.gitignore
على سبيل المثال إذا كنت ترغب في تصفية ملفات PDF، أضف ! -name '*.pdf'
$ find /my/dir/ -printf "%P\n" -type f ! -name '*.pdf' -o -type l -o -type d
> textfile.txt
> subfolder2
> subfolder
> subfolder/.gitignore
العثور على غير جنو
يستخدم الأمر printf
(متوفر في جنو find
) الذي يخبره find
لطباعة نتائجها بالمسارات النسبية. ومع ذلك، إذا لم يكن لديك جنو find
, ، هذا يعمل لجعل المسارات قريب (يزيل الآباء sed
):
find /my/dir/ -type f -o -type l -o -type d | sed s,^/my/dir/,, | tar -czf mydir.tgz --no-recursion -C /my/dir/ -T -
هذه الإجابة يجب أن تعمل في معظم الحالات. لاحظ كيف يتم تخزين أسماء الملفات في ملف القطران، على سبيل المثال، ./file1
افضل من مجرد file1
. وبعد لقد وجدت أن هذا تسبب في مشاكل عند استخدام هذه الطريقة لمعالجة Tarballs المستخدمة كملفات حزمة في buildroot..
أحد الحلول هو استخدام بعض غضاب الباش لسرد جميع الملفات باستثناء ..
مثله:
tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *
هذه خدعة تعلمتها من هذه الإجابة.
الآن سوف يرجع القطران خطأ إذا لم تكن هناك ملفات مطابقة ..?*
أو .[^.]*
، ولكنها ستظل تعمل. إذا كان الخطأ مشكلة (تقوم بالتحقق من النجاح في برنامج نصي)، فهذا يعمل:
shopt -s nullglob
tar -C my_dir -zcvf my_dir.tar.gz .[^.]* ..?* *
shopt -u nullglob
على الرغم من أننا الآن نحن العبث بخيارات شل، فقد نقرر أن يكون هذا *
تطابق الملفات المخفية:
shopt -s dotglob
tar -C my_dir -zcvf my_dir.tar.gz *
shopt -u dotglob
هذا قد لا يعمل حيث غلوب شل الخاص بك *
في الدليل الحالي، لذلك بدلا من ذلك، استخدم:
shopt -s dotglob
cd my_dir
tar -zcvf ../my_dir.tar.gz *
cd ..
shopt -u dotglob
cd my_directory
tar zcvf ../my_directory.tar.gz *
إذا كان نظام UNIX / Linux، وأنت تهتم بالملفات المخفية (والتي سيتم تفويتها بواسطة *)، تحتاج إلى القيام به:
cd my_directory
tar zcvf ../my_directory.tar.gz * .??*
لا أعرف مثل الملفات المخفية تبدو تحت نوافذ.
أود أن أقترح وظيفة الباش التالية (الوسيطة الأولى هي المسار إلى DIR، والوسيطة الثانية هي اسم الأرشيف الناتج):
function tar_dir_contents ()
{
local DIRPATH="$1"
local TARARCH="$2.tar.gz"
local ORGIFS="$IFS"
IFS=$'\n'
tar -C "$DIRPATH" -czf "$TARARCH" $( ls -a "$DIRPATH" | grep -v '\(^\.$\)\|\(^\.\.$\)' )
IFS="$ORGIFS"
}
يمكنك تشغيله بهذه الطريقة:
$ tar_dir_contents /path/to/some/dir my_archive
وسوف تولد الأرشيف my_archive.tar.gz
ضمن الدليل الحالي. يعمل مع عناصر مخفية (. *) ومع العناصر ذات المسافات في اسم ملفهم.
cd my_directory && tar -czvf ../my_directory.tar.gz $(ls -A) && cd ..
هذا واحد يعمل بالنسبة لي ويشمل جميع الملفات المخفية دون وضع جميع الملفات في دليل جذر يدعى "." كما هو الحال في إجابة تومو :
استخدام pax.
باكس عبارة عن حزمة مهملة ولكنها المهمة تماما وبأزياء بسيطة.
pax -w > mydir.tar mydir
أبسط طريقة وجدت:
CD MY_DIR && TAR -CZVF ../my_dir.tar.gz *
# tar all files within and deeper in a given directory
# with no prefixes ( neither <directory>/ nor ./ )
# parameters: <source directory> <target archive file>
function tar_all_in_dir {
{ cd "$1" && find -type f -print0; } \
| cut --zero-terminated --characters=3- \
| tar --create --file="$2" --directory="$1" --null --files-from=-
}
يعالج بأمان أسماء الملفات مع مسافات أو أحرف غير عادية أخرى. يمكنك اختياريا إضافة -name '*.sql'
أو مرشح مشابه إلى أمر البحث للحد من الملفات المضمنة.
tar -cvzf tarlearn.tar.gz --remove-files mytemp/*
إذا كان المجلد MyTemp، إذا قمت بتطبيق ما سبق، فسوف يقوم بإعادة ضغط جميع الملفات وإزالتها في المجلد
tar -cvzf tarlearn.tar.gz --remove-files --exclude='*12_2008*' --no-recursion mytemp/*
يمكنك إعطاء أنماط استبعاد وتحديد أيضا عدم النظر في مجلدات فرعية أيضا
tar -C my_dir -zcvf my_dir.tar.gz `ls my_dir`