كيف يمكنني القطران دليل الملفات والمجلدات دون إدراج الدليل نفسه؟

StackOverflow https://stackoverflow.com/questions/939982

  •  06-09-2019
  •  | 
  •  

سؤال

أنا عادة ما تفعل:

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`
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top