جعل xargs تنفيذ الأمر مرة واحدة لكل سطر الإدخال
-
11-07-2019 - |
سؤال
كيف يمكنني جعل xargs تنفيذ الأمر بالضبط مرة واحدة في كل خط من المدخلات ؟ هذا هو السلوك الافتراضي هو قطعة خطوط و تنفيذ الأمر مرة واحدة ، ويمر خطوط متعددة إلى كل حالة.
من http://en.wikipedia.org/wiki/Xargs:
تجد /path من نوع f-print0 | xargs -0 rm
في هذا المثال تجد يغذي المدخلات من xargs مع قائمة طويلة من أسماء الملفات.xargs ثم تنقسم هذه القائمة إلى sublists ويدعو rm مرة واحدة لكل sublist.هذا هو أكثر كفاءة من هذا وظيفيا الإصدار:
تجد /path من نوع f-exec rm '{}' \;
وأنا أعلم أن تجد لديه "exec" العلم.أنا أقتبس فقط مثال توضيحي من مورد آخر.
المحلول
وفيما يلي تنجح إلا إذا لم يكن لديك مسافات في الإدخال:
xargs -L 1
xargs --max-lines=1 # synonym for the -L option
من الصفحة رجل:
-L max-lines
Use at most max-lines nonblank input lines per command line.
Trailing blanks cause an input line to be logically continued on
the next input line. Implies -x.
نصائح أخرى
يبدو لي كل القائمة إجابات على هذه الصفحة خاطئة ، بما في ذلك وضع علامة الصحيح.هذا ينبع من حقيقة أن المسألة غامضة الصياغة.
موجز: إذا كنت ترغب في تنفيذ الأمر "مرة واحدة في كل خط من مدخل معين،" ويمر خط كامل (بدون السطر) إلى الأمر باعتباره واحد حجة ، ثم وهذا هو أفضل UNIX متوافق مع طريقة للقيام بذلك:
... | tr '\n' '\0' | xargs -0 -n1 ...
جنو xargs
قد أو قد لا يكون الملحقات المفيدة التي تسمح لك أن تفعل بعيدا مع tr
, لكنهم لا تتوفر على OS X وغيرها من أنظمة UNIX.
الآن لفترة طويلة تفسير...
هناك نوعان من القضايا التي تأخذ في الاعتبار عند استخدام xargs:
- كيف تقسيم المدخلات في "حجج";و
- كيف العديد من الحجج لتمرير الطفل الأوامر في وقت واحد.
لاختبار xargs سلوك ، نحن بحاجة إلى الأداة التي يظهر كم عدد المرات التي يجري تنفيذها مع كم من الحجج.أنا لا أعرف إذا كان هناك معيار المنفعة للقيام بذلك ، ولكن يمكننا أن قانون ذلك بسهولة تامة في bash:
#!/bin/bash
echo -n "-> "; for a in "$@"; do echo -n "\"$a\" "; done; echo
على افتراض كنت احفظ show
في الدليل الحالي وجعلها قابلة للتنفيذ, هنا هو كيف يعمل:
$ ./show one two 'three and four'
-> "one" "two" "three and four"
الآن, إذا كان السؤال الأصلي هو حقا حول نقطة 2.أعلاه (كما أعتقد أنه بعد قراءته عدة مرات أكثر) و هو أن تقرأ مثل هذا (التغييرات في جريئة):
كيف يمكنني جعل xargs تنفيذ الأمر بالضبط مرة واحدة لكل الحجة من المدخلات ؟ السلوك الافتراضي هو قطعة من الإدخال إلى الحجج وتنفيذ الأوامر كما عدة مرات ممكن, تمرير متعددة الحجج إلى كل حالة.
ثم الجواب -n 1
.
دعونا نقارن xargs' السلوك الافتراضي الذي يقسم إدخال جميع أنحاء بيضاء وتطلب الأمر عدة مرات ممكن:
$ echo one two 'three and four' | xargs ./show
-> "one" "two" "three" "and" "four"
وسلوكه مع -n 1
:
$ echo one two 'three and four' | xargs -n 1 ./show
-> "one"
-> "two"
-> "three"
-> "and"
-> "four"
إذا ، من ناحية أخرى ، الأصلي كان السؤال عن النقطة 1.المدخلات تقسيم يمكن قراءة مثل هذا (كثير من الناس يأتون إلى هنا يبدو أن أعتقد أن هذا هو الحال ، أو يتم الخلط بين المسألتين):
كيف يمكنني جعل xargs تنفيذ الأمر مع بالضبط حجة واحدة لكل خط من المدخلات ؟ السلوك الافتراضي هو قطعة الخطوط حول بيضاء.
ثم الجواب هو أكثر مكرا.
قد يعتقد المرء أن -L 1
يمكن أن تساعد ولكن اتضح أنه لا يغير حجة تحليل.هو فقط ينفذ الأوامر مرة واحدة لكل سطر الإدخال ، مع العديد من الحجج كما كانت هناك على سطر الإدخال:
$ echo $'one\ntwo\nthree and four' | xargs -L 1 ./show
-> "one"
-> "two"
-> "three" "and" "four"
ليس هذا فقط, ولكن إذا كان خط ينتهي بيضاء ، فإنه يتم إلحاق التالي:
$ echo $'one \ntwo\nthree and four' | xargs -L 1 ./show
-> "one" "two"
-> "three" "and" "four"
بوضوح ، -L
لا حول تغيير طريقة xargs يقسم الإدخال إلى الحجج.
الحجة الوحيدة التي تفعل ذلك عبر منصة الأزياء (باستثناء جنو امتداد) ، -0
, الذي يقسم الإدخال حول NUL بايت.
ثم انها مجرد مسألة ترجمة أسطر إلى NUL مع مساعدة من tr
:
$ echo $'one \ntwo\nthree and four' | tr '\n' '\0' | xargs -0 ./show
-> "one " "two" "three and four"
الآن حجة تحليل يبدو على ما يرام ، بما في ذلك زائدة بيضاء.
أخيرا, إذا كنت الجمع بين هذه التقنية مع -n 1
, ، يمكنك الحصول على واحد بالضبط تنفيذ الأمر في سطر الإدخال ، أيا كان الإدخال لديك ، والتي قد تكون طريقة أخرى للنظر في السؤال الأصلي (ربما الأكثر بديهية ، نظرا العنوان):
$ echo $'one \ntwo\nthree and four' | tr '\n' '\0' | xargs -0 -n1 ./show
-> "one "
-> "two"
-> "three and four"
إذا كنت ترغب في تشغيل الأوامر على كل الخط (أينتيجة) قادمة من find
, ثم ماذا تحتاج xargs
؟
محاولة:
find
المسار -type f -exec
الخاص بك القيادة {} \;
حيث الحرفي {}
يتم استبداله من قبل اسم الملف و الحرفي \;
مطلوب find
أن تعرف أن العرف الأمر ينتهي هناك.
تحرير:
(بعد تعديل السؤال يوضح أن تعرف عن -exec
)
من man xargs
:
-L ماكس-خطوط
تستخدم في أكثر من ماكس-خطوط nonblank إدخال خطوط في سطر الأوامر.زائدة الفراغات يسبب سطر الإدخال أن يكون منطقيا استمرار التالي سطر الإدخال.يعني -x.
لاحظ أن أسماء الملفات التي تنتهي في الفراغات قد يسبب لك المتاعب إذا كنت تستخدم xargs
:
$ mkdir /tmp/bax; cd /tmp/bax
$ touch a\ b c\ c
$ find . -type f -print | xargs -L1 wc -l
0 ./c
0 ./c
0 total
0 ./b
wc: ./a: No such file or directory
حتى إذا كنت لا أهتم -exec
الخيار الأفضل استخدام -print0
و -0
:
$ find . -type f -print0 | xargs -0L1 wc -l
0 ./c
0 ./c
0 ./b
0 ./a
وكيف يمكنني أن أجعل xargs تنفيذ الأمر بالضبط مرة واحدة لكل خط من مدخلات معينة؟
اقتباس فقرة> وأنا لا تستخدم الإجابة -L 1
لأنه لا يعالج الملفات مع المساحات في تلك التي هي وظيفة أساسية من find -print0
.
echo "file with space.txt" | xargs -L 1 ls
ls: file: No such file or directory
ls: space.txt: No such file or directory
ls: with: No such file or directory
والحل الأفضل هو استخدام tr
لتحويل أسطر فارغة (\0
) حرفا، ومن ثم استخدام الوسيطة xargs -0
.
echo "file with space.txt" | tr '\n' '\0' | xargs -0 ls
file with space.txt
إذا كنت تحتاج بعد ذلك للحد من عدد المكالمات التي يمكن استخدام الوسيطة -n 1
لإجراء مكالمة واحدة إلى برنامج لكل المدخلات:
echo "file with space.txt" | tr '\n' '\0' | xargs -0 -n 1 ls
وهذا أيضا يسمح لك لتصفية إخراج العثور <م> قبل م> تحويل فواصل إلى بالقيم الخالية.
find . -name \*.xml | grep -v /workspace/ | tr '\n' '\0' | xargs -0 tar -cf xml.tar
وثمة بديل آخر ...
find /path -type f | while read ln; do echo "processing $ln"; done
find path -type f | xargs -L1 command
وهو كل ما تحتاج.
وتعمل هذه الطريقتين أيضا، وسوف تعمل من الأوامر الأخرى التي لا تستخدم تجد!
xargs -I '{}' rm '{}'
xargs -i rm '{}'
والمثال حالة الاستخدام:
find . -name "*.pyc" | xargs -i rm '{}
وسيتم حذف جميع الملفات PYC ضمن هذا الدليل حتى إذا كانت الملفات PYC تحتوي على مسافات.
والأمر التالي سوف تجد كافة الملفات (من نوع و) في /path
ثم نسخها باستخدام cp
إلى المجلد الحالي. لاحظ استخدام إذا -I %
لتحديد شخصية نائب في سطر الأوامر cp
بحيث الحجج التي يمكن أن توضع بعد اسم الملف.
وfind /path -type f -print0 | xargs -0 -I % cp % .
واختبار مع xargs (findutils GNU) 4.4.0
ويمكنك الحد من عدد من الخطوط، أو الحجج (إذا كان هناك مسافات بين كل حجة) باستخدام خطوط --max أو وسائط --max الأعلام، على التوالي.
<اقتباس فقرة> -L max-lines
Use at most max-lines nonblank input lines per command line. Trailing blanks cause an input line to be logically continued on the next input
line. Implies -x.
--max-lines[=max-lines], -l[max-lines]
Synonym for the -L option. Unlike -L, the max-lines argument is optional. If max-args is not specified, it defaults to one. The -l option
is deprecated since the POSIX standard specifies -L instead.
--max-args=max-args, -n max-args
Use at most max-args arguments per command line. Fewer than max-args arguments will be used if the size (see the -s option) is exceeded,
unless the -x option is given, in which case xargs will exit.
اقتباس فقرة> ويبدو أنني لم يكن لديك ما يكفي من سمعة لإضافة تعليق على الجواب طوبيا في ما سبق ، لذلك أنا وأضاف هذا "الإجابة" لمساعدة أولئك منا الذين يريدون تجربة xargs
بنفس الطريقة على أنظمة تشغيل ويندوز.
وهنا هو ملف ويندوز دفعة أن يفعل الشيء نفسه النصي طوبيا ومشفرة بسرعة "إظهار":
@echo off
REM
REM cool trick of using "set" to echo without new line
REM (from: http://www.psteiner.com/2012/05/windows-batch-echo-without-new-line.html)
REM
if "%~1" == "" (
exit /b
)
<nul set /p=Args: "%~1"
shift
:start
if not "%~1" == "" (
<nul set /p=, "%~1"
shift
goto start
)
echo.
وDraemon الإجابات يبدو أن الحق مع "-0" حتى مع وجود مساحة في الملف.
وكنت أحاول الأمر xargs ولقد وجدت أن "-0" يعمل تماما مع "لام". يتم التعامل حتى مسافات (إذا تم إنهاء إدخال فارغة). وفيما يلي مثال:
#touch "file with space"
#touch "file1"
#touch "file2"
وفيما يلي سوف تقسيم بلا قيم وتنفيذ الأمر على كل حجة في القائمة:
#find . -name 'file*' -print0 | xargs -0 -L1
./file with space
./file1
./file2
وهكذا -L1
سيتم تنفيذ حجة على كل حرف منتهية إذا ما استخدمت مع "-0". لمعرفة الفرق المحاولة:
#find . -name 'file*' -print0 | xargs -0 | xargs -L1
./file with space ./file1 ./file2
وحتى هذا سيتم تنفيذ مرة واحدة:
#find . -name 'file*' -print0 | xargs -0 | xargs -0 -L1
./file with space ./file1 ./file2
والأمر سيتم تنفيذ مرة واحدة باسم "لام" الآن لا تقسيم على بايت فارغة. تحتاج إلى توفير كل من "-0" و "لام" للعمل.
في المثال الخاص بك، وهذه النقطة من الأنابيب إخراج العثور على xargs هي أن السلوك القياسي الخيار العثور على -exec هو تنفيذ الأمر مرة واحدة لكل ملف تم العثور عليها. إذا كنت تستخدم بحث، وتريد سلوكها القياسية، ثم الجواب بسيط - لا تستخدم xargs لتبدأ
وتنفيذ المهمة النمل نظيفة للجميع على كل build.xml على الحالي أو دون المجلد.
find . -name 'build.xml' -exec ant -f {} clean-all \;