Як я магу зрабіць xargs апрацоўваць імёны файлаў, якія ўтрымліваюць прабелы?

$ ls *mp3 | xargs mplayer  

Playing Lemon.  
File not found: 'Lemon'  
Playing Tree.mp3.  
File not found: 'Tree.mp3'  

Exiting... (End of file)  

Мая каманда не таму, што файл «Lemon Tree.mp3» змяшчае прабелы, таму xargs лічыць, што гэта два файла. Ці магу я зрабіць знаходкі + xargs працаваць з імёнамі файлаў, як гэта?

179
Замест Ls | Grep mp3 | СЭД -n "7Р" вы можаце проста выкарыстоўваць рэха "Lemon Tree.mp3" .
дададзена аўтар Micha Wiedenmann, крыніца
Гэтае пытанне таксама адказаў на stackoverflow.com/a/33528111/94687
дададзена аўтар imz -- Ivan Zakharyaschev, крыніца

12 адказы

Ўтыліта xargs чытае прабел, табуляцыя, пераклад радка і канец з файла з падзельнікамі радкі з стандартнага ўводу і выконвае праграму з радкамі ў якасці аргументаў.

Вы хочаце, каб пазбегнуць выкарыстання прасторы ў якасці падзельніка. Гэта можа быць зроблена шляхам змены падзельніка для xargs. Па словах кіраўніцтва:

<�Папярэдне> -0 Змяніць xargs чакаць NUL сімвалаў ( `` \ 0 '') у якасці падзельнікаў,          замест прабелаў і перакладаў радкоў. Гэта, як чакаецца, будзе выкарыстоўвацца ў          канцэрт з -print0 функцыі ў знаходцы (1).

Такія як:

 find . -name "*.mp3" -print0 | xargs -0 mplayer

Для таго, каб адказаць на пытанне аб гульні кожны сёмы mp3; гэта прасцей працаваць

 mplayer "$(ls | grep mp3 | sed -n 7p)"
190
дададзена
Гэта выкарыстанне GNU знайсці і GNU xargs ; не ўсе версіі гэтых праграм падтрымліваюць гэтыя варыянты (хоць ёсць выпадак, які будзе зроблена, што яны павінны).
дададзена аўтар Jonathan Leffler, крыніца
І Mac OS X (а BSD вытворнай) мае знайсці з -print0 і xargs з -0 . AFAIK, HP-UX, AIX і Solaris ня, аднак (але я стаю выправіцца: HP-UX 11i ня; Solaris 10. ня; AIX 5.x ня, але яны не бягучыя версіі ). Гэта не было б цяжка змяніць </патч у код>, напрыклад, выкарыстоўваць «радкі» заканчваючы «\ 0» замест «\ п» </код > і POSIX 2008 getdelim() </а> дазволіць лёгка кіраваць.
дададзена аўтар Jonathan Leffler, крыніца
@ User2807219: Я хацеў бы ведаць, як вы паказваеце, што. Гэта працуе для мяне. У выпадку неабходнасці, адправіць мне па электроннай пошце - гл мой профіль - і ўключыць спасылку на гэтае пытанне і MCVE, які дэманструе, як вы сутыкнецеся з праблемамі.
дададзена аўтар Jonathan Leffler, крыніца
@ User2807219: Гэта цікава. Гэта таксама зусім розныя. Я калі-то праблема з тэстам канфігурацыі праграмнага забеспячэння, што не атрымалася на вельмі, вельмі глыбокія іерархіі каталогаў на Mac - ён спрабуе праверыць, наколькі глыбока яны маглі б пайсці і заблыталася, дапамаглі памылкай Mac OS X. Але гэта было б незвычайна. Альбо стварыць свой уласны пытанне з выкладаннем праблемы або звязацца са мной у аўтаномным рэжыме з дэталямі. Ёсць, верагодна, спосабы барацьбы з ім, але вы павінны ведаць і растлумачыць, чаму ў цябе такія доўгія імёны, ілюструюць некаторыя прыклады (яны не будуць ўпісвацца ў каментарах), і растлумачыць, што вы спрабуеце зрабіць.
дададзена аўтар Jonathan Leffler, крыніца
@JonathanLeffler с/ХІЛЮ/FreeBSD/г; POSIX, на жаль, баіцца сімвалаў NUL ў тэкставых файлах і не было дастаткова тэрапіі яшчэ :-) Мая парада на самай справе курортаў для непераноснасці варыянтаў.
дададзена аўтар Jens, крыніца
Добрая ідэя замяніць новай радкі з NUL - я павінен быў зрабіць гэта на ўбудаванай сістэме, якія не маюць GNU знайсці, ні GNU xargs, ні Perl - але каманда тр можа быць выкарыстана, каб зрабіць тое ж самае: кошка $ file_paths_list_file | тр '\ п' \ 0 '| xargs -0 дзю -hms
дададзена аўтар joensson, крыніца
+1 + 1 трук для выкарыстання з шляхамі файлаў, якія змяшчаюць спіс файлаў: кошкі $ file_paths_list_file | Perl -ne 's | \ п | \ 000 | г, друк' | xargs -0 зип $ zip_package
дададзена аўтар Yordan Georgiev, крыніца
@YordanGeorgiev свой каментар (асабліва з выкарыстаннем @ joensson аб тр замест Perl) павінен быць адказ!
дададзена аўтар Ahmed Fasih, крыніца
@JonathanLeffler, дзякуй за адказ, я паспрабаваў яшчэ раз, праблема не прастору, знайсці з xargs працуе на прасторы файла нават без -print0 і -0. Мая рэальная праблема заключаецца імёны тэчак і імёны файлаў занадта доўга, то вынік выканання «мв: перайменаваць {} к/pathTo/{}: Няма такога файла ці каталога».
дададзена аўтар user2807219, крыніца
@JonathanLeffler, хоць MacOS мае -print0 і -0, ён не працуе, калі імя файла ўтрымлівае прабел.
дададзена аўтар user2807219, крыніца

<�Код> xargs Каманда прымае пробельные сімвалы (укладкі, прабелы, новыя лініі) у якасці падзельнікаў. Вы можаце звузіць гэта толькі для новых сімвалаў радка ( «\ п») з -d опцыя, як гэта:

ls *.mp3 | xargs -d '\n' mplayer

Яна працуе толькі з GNU xargs. Для сістэм BSD, выкарыстоўвайце -0 опцыі, як гэта:

ls *.mp3 | xargs -0 mplayer

Гэты метад з'яўляецца больш простым і працуе з xargs GNU, а таксама.

140
дададзена
gxargs на перамогу
дададзена аўтар tofutim, крыніца
На жаль, гэтая опцыя не даступная на OS X.
дададзена аўтар Thomas Tempelmann, крыніца
Для OS X, вы можаце «заварыць ўсталяваць Findutils», які дае вам «gxargs» каманду, гэта </я> маюць ключ -d.
дададзена аўтар Tom De Leu, крыніца
Лепшы адказ для агульнага карыстання! Гэта працуе, нават калі ваша папярэдняя каманда не «знайсці»
дададзена аўтар nexayq, крыніца
На OS X, -E «\ п» не мае эфекту для мяне, ні я б чакаць, што яна, як яна змяніла eofstr і ня падзельнік запісаў. Тым не менш, я быў у стане выкарыстаць -0 сцяг у якасці рашэння, нават калі папярэдняя каманда не «знайсці», шляхам імітацыі эфекту -print0 сцяга знайсці ў маім ўваходзе, напрыклад.: Ls * mp3 | тр '\ п' \ 0 '| xargs -0 MPlayer
дададзена аўтар biomiker, крыніца
@Thomas для OS X, сцяг -E , напрыклад: xargs -E '\ п'
дададзена аўтар user2062950, крыніца

спрабаваць

find . -name \*.mp3 -print0 | xargs -0 mplayer

замест

ls | grep mp3 
20
дададзена

xargs на MacOS не мае опцыі -d, так што гэта рашэнне выкарыстоўвае -0 замест гэтага.

Атрымаць ашчадны выхад адзін файл у кожнай радок, а затым перавесці ў новых радкі нулёў і сказаць xargs выкарыстоўваць анулююць ў якасці падзельніка:

<�Код> Ls -1 * mp3 | тр "\ п" "\ 0" | xargs -0 MPlayer

8
дададзена

Адказ Dick.Guertin [1] адзначыў, што можна было б пазбегнуць прабелы ў імя файла з'яўляецца каштоўнай альтэрнатывай іншым рашэнням прапанаваў тут (напрыклад, з выкарыстаннем нулявога сімвала ў якасці падзельніка, а не прабеламі). Але гэта можа быць прасцей - вы на самой справе не патрэбен унікальны характар. Вы можаце проста дадаць яшчэ СЭД ўцяклі прасторы непасрэдна:

ls | grep ' ' | sed 's| |\\ |g' | xargs ...

Акрамя таго, Grep неабходны, толькі калі вы толькі хоча, каб файлы з прабеламі ў імёнах. Больш абагульнена (напрыклад, пры апрацоўцы пакета файлаў, некаторыя з якіх маюць прабелы, некаторыя няма), проста прапусціць Grep:

ls | sed 's| |\\ |g' | xargs ...

Тады, вядома, імя файла можа мець іншыя прабелы, чым нарыхтовак (напрыклад, укладкі):

ls | sed -r 's|[[:blank:]]|\\\1|g' | xargs ...

That assumes you have a sed that supports -r (extended regex) such as GNU sed or recent versions of bsd sed (e.g., FreeBSD which originally spelled the option "-E" before FreeBSD 8 and supports both -r & -E for compatibility through FreeBSD 11 at least). Otherwise you can use a basic regex character class bracket expression and manually enter the space and tab characters in the [] delimiters.

[1] Гэта, магчыма, больш дарэчы ў якасці каментара або праўкі гэтага адказу, але на дадзены момант у мяне няма дастаткова рэпутацыі каментаваць і магу прапанаваць толькі змены. Паколькі гэтыя формы вышэй (без Grep) змяняюць паводзіны арыгінальнага адказу Dick.Guertin, у прамым рэдагаванне, магчыма, не падыходзіць у любым выпадку.

5
дададзена
Імя файла з язычком ў ім! Хто робіць такія рэчы ???
дададзена аўтар glyph, крыніца
вар'ят UNIX хлопцы, якія кіруюць сцэнарамі, імёны файлаў без уліку іх вываду, што ёсць хто
дададзена аўтар andrew lorien, крыніца
find . -name 'Lemon*.mp3' -print0 | xargs -­0 -i mplayer '{}' 

Гэта дапамагло ў маім выпадку, каб выдаліць розныя файлы з прабеламі. Ён таксама павінен працаваць з MPlayer. Неабходная Хітрасць заключаецца ў двукоссях. (Праверана на Linux Xubuntu 14,04.)

5
дададзена

<�Код> Ls | Grep mp3 | СЕПГ -n «7Р» | xargs -i MPlayer {}

Звярніце ўвагу, што ў камандзе вышэй, xargs патэлефануе MPlayer нанова для кожнага файла. Гэта можа быць непажаданым для MPLAYER , але можа быць добра для іншых мэтаў.

4
дададзена
Гэта, верагодна, як правіла, не з'яўляецца мэтай. <�Код> xargs у асноўным выкарыстоўваюцца з камандамі, якія прымаюць спіс імёнаў файлаў (просты прыклад: ет ), і спрабуе перадаць, як шмат імёнаў файлаў, як гэта можа змясціцца ў кожны выклік, пры неабходнасці толькі падзяліўшы на некалькі выклікаў. Вы можаце ўбачыць розніцу, калі вы выкарыстоўваеце каманду, дзе кожны выклік бачны, напрыклад, рэха (па змаўчанні): сл 0 100000 | xargs друкуе ўсе лікі ад 0 да 23695 (залежыць ад платформы, але гэта тое, што адбываецца ў маёй сістэме) на першай лініі, да 45539 у радку 2, і г.д. І вы маеце рацыю, для большасці каманд, ён выйграў «т справа.
дададзена аўтар hvd, крыніца
Карысным дадаткам да існуючых адказаў, але гэта варта было б адзначыць, што гэта прывядзе да MPLAYER будзе называцца зноўку для кожнага файла. Гэта важна, калі вы спрабуеце, напрыклад, <�Код> ... | xargs -I {} MPlayer -shuffle {} : гэта будзе гуляць у зусім няпэўным парадку, нягледзячы на ​​ -shuffle .
дададзена аўтар hvd, крыніца

I know that I'm not answering the <�Код> xargs question directly but it's worth mentioning find's -exec option.

Улічваючы наступны файл сістэмы:

[[email protected] bokeh]# tree --charset assci bands
bands
|-- Dream\ Theater
|-- King's\ X
|-- Megadeth
`-- Rush

0 directories, 4 files

Каманду знаходкі можна апрацоўваць прастору ў Dream Theater і кароль X. Такім чынам, каб знайсці бубнач кожнай паласы з дапамогай Grep:

[[email protected]]# find bands/ -type f -exec grep Drums {} +
bands/Dream Theater:Drums:Mike Mangini
bands/Rush:Drums: Neil Peart
bands/King's X:Drums:Jerry Gaskill
bands/Megadeth:Drums:Dirk Verbeuren

У опцыя -exec {} азначае імя файла, уключаючы шлях. Звярніце ўвагу, што вам не трэба, каб пазбегнуць яго або пакласці яго ў двукоссі.

Розніца паміж -exec 's тэрмінатара ( + і \ ), што + групы, як шмат імёнаў файлаў што ён можа на адной каманднага радку. У той час як \; выканае каманду для кожнага імя файла.

Так, знайсці групы/-тыпу е -exec Grep Барабаны {} + будзе прыводзіць да:

grep Drums "bands/Dream Theater" "bands/Rush" "bands/King's X" "bands/Megadeth"

і знайсці групы/-тыпу е -exec Grep Барабаны {} \; прывядзе да:

grep Drums "bands/Dream Theater"
grep Drums "bands/Rush"
grep Drums "bands/King's X"
grep Drums "bands/Megadeth"

У выпадку Grep гэта мае пабочны эфект альбо надрукаваць імя файла ці не.

[[email protected] bokeh]# find bands/ -type f -exec grep Drums {} \;
Drums:Mike Mangini
Drums: Neil Peart
Drums:Jerry Gaskill
Drums:Dirk Verbeuren

[[email protected] bokeh]# find bands/ -type f -exec grep Drums {} +
bands/Dream Theater:Drums:Mike Mangini
bands/Rush:Drums: Neil Peart
bands/King's X:Drums:Jerry Gaskill
bands/Megadeth:Drums:Dirk Verbeuren

Вядома, Grep 's опцыі -h і -H будзе кантраляваць, ці будзе ці не друкуецца імя файла, незалежна ад таго, як Grep называецца.


<�Код> xargs

<�Код> xargs can also control how man files are on the command line.

<�Код> xargs by default groups all the arguments onto one line. In order to do the same thing that -exec \; does use xargs -l. Note that the -t option tells <�Код> xargs to print the command before executing it.

[[email protected] bokeh]# find ./bands -type f  | xargs -d '\n' -l -t grep Drums
grep Drums ./bands/Dream Theater 
Drums:Mike Mangini
grep Drums ./bands/Rush 
Drums: Neil Peart
grep Drums ./bands/King's X 
Drums:Jerry Gaskill
grep Drums ./bands/Megadeth 
Drums:Dirk Verbeuren

Глядзіце, што -l опцыя кажа xargs для выканання Grep для кожнага файла.

Versus па змаўчанні (гэта значыць няма -l опцыя):

[[email protected] bokeh]# find ./bands -type f  | xargs -d '\n'  -t grep Drums
grep Drums ./bands/Dream Theater ./bands/Rush ./bands/King's X ./bands/Megadeth 
./bands/Dream Theater:Drums:Mike Mangini
./bands/Rush:Drums: Neil Peart
./bands/King's X:Drums:Jerry Gaskill
./bands/Megadeth:Drums:Dirk Verbeuren

<�Код> xargs has better control on how many files can be on the command line. Give the -l option the max number of files per command.

[[email protected] bokeh]# find ./bands -type f  | xargs -d '\n'  -l2 -t grep Drums
grep Drums ./bands/Dream Theater ./bands/Rush 
./bands/Dream Theater:Drums:Mike Mangini
./bands/Rush:Drums: Neil Peart
grep Drums ./bands/King's X ./bands/Megadeth 
./bands/King's X:Drums:Jerry Gaskill
./bands/Megadeth:Drums:Dirk Verbeuren
[[email protected] bokeh]# 

Глядзіце, што Grep быў выкананы з двума імёнамі файлаў з-за -l2 .

2
дададзена

Гэта залежыць ад (а), як прыкладзеныя вы да ліку 7, у адрозненне ад, скажам, цытрын, і (б) любы з вашых імёнаў файлаў ці ўтрымліваюць сімвалы новага радка (і вы гатовыя перайменаваць іх, калі яны робяць).

Ёсць шмат спосабаў барацьбы з ім, але некаторыя з іх:

mplayer Lemon*.mp3

find . -name 'Lemon*.mp3' -exec mplayer {} ';'

i=0
for mp3 in *.mp3
do
    i=$((i+1))
    [ $i = 7 ] && mplayer "$mp3"
done

for mp3 in *.mp3
do
    case "$mp3" in
    (Lemon*) mplayer "$mp3";;
    esac
done

i=0
find . -name *.mp3 |
while read mp3
do
    i=$((i+1))
    [ $i = 7 ] && mplayer "$mp3"
done

<�Код> прачытаць пятля не працуе, калі імёны файлаў ўтрымліваюць сімвалы новага радка; астатнія правільна працаваць нават з новай радком у назвах (не кажучы ўжо пра прабелах). За свае грошы, калі ў вас ёсць імёны файлаў, якія змяшчаюць радок, вы павінны перайменаваць файл без перакладу радка. Выкарыстоўваючы падвойныя двукоссі вакол імя файла з'яўляецца ключом да завес працуе правільна.

Калі ў вас ёсць GNU знайсці і GNU xargs (ці FreeBSD (* BSD?), Або Mac OS X), вы таксама можаце выкарыстоўваць -print0 </код > і -0 параметры, як у:

find . -name 'Lemon*.mp3' -print0 | xargs -0 mplayer

Гэта працуе незалежна ад зместу назвы (толькі два сімвала, якія не могуць з'яўляцца ў імя файла з'яўляецца слэшам і NUL, і слэш не выклікае ніякіх праблем у шляху да файла, так што выкарыстанне NUL як імя падзельнік ахоплівае ўсе). Тым не менш, калі вам трэба адфільтраваць першыя 6 запісаў, вам патрэбна праграма, якая апрацоўвае «лінія» скончылася NUL замест новага радка ... і я не ўпэўнены, што яны ёсць.

Па-першае, на сённяшні дзень самы просты для канкрэтнага выпадку на руцэ; Аднак, гэта не можа абагульняць, каб пакрыць іншыя сцэнары, якія вы яшчэ не пералічаныя.

2
дададзена

На MacOS 10.12.x (Sierra), калі ў вас ёсць прабелы ў імёнах файлаў ці падкаталогаў, вы можаце выкарыстоўваць наступнае:

find . -name '*.swift' -exec echo '"{}"' \; |xargs wc -l
2
дададзена

Улічваючы канкрэтную назву гэтай пасады, вось мая прапанова:

ls | grep ' ' | tr ' ' '<' | sed 's|<|\\ |g'

The idea is to convert blanks to any unique character, like '<', and then change that into '\ ', a backslash followed by a blank. You can then pipe that into any command you like, such as:

ls | grep ' ' | tr ' ' '<' | sed 's|<|\\ |g' | xargs -L1 GetFileInfo

The key here lies in the 'tr' and 'sed' commands; and you can use any character besides '<', such as '?' or even a tab-character.

1
дададзена
Што мэта аб'езд праз тр ? Чаму не толькі Ls * .mp3 | Сед -n '7 б, с/\! ([[: Плошча:]] \)/\\\ 1/г; р' ?
дададзена аўтар tripleee, крыніца
Я выявіў, што «тр" ""? "» Ухіляе неабходнасць у "СЭД». Сінгл «?» знак не з'яўляецца пустым, але адпавядае любому знаку, у дадзеным выпадку: пуста. Шанцы таго, што гэта нешта яшчэ вельмі малыя, і прымальныя, так як вы спрабуеце апрацаваць усе файлы, якія сканчаюцца ў .mp3 :? «LS | Grep" "| тр" "" " | Xargs -L1 GetFileInfo »
дададзена аўтар Dick Guertin, крыніца
Вы таксама можаце звяртацца «на ўкладцы" ў той жа час: тр «\ т» «??» ручкі і іншыя.
дададзена аўтар Dick Guertin, крыніца

Альтэрнатыўныя рашэнні могуць быць карысныя ...

You can also add a null character to the end of your lines using Perl, then use the -0 option in xargs. Unlike the xargs -d '\n' (in approved answer) - this works everywhere, including OS X.

Напрыклад, каб рэкурсіўна спіс (выканаць, перамяшчэнне і г.д.) выявы ў фармаце JPEG, якія могуць утрымліваць прабелы або іншыя цікавыя персанажы - я хацеў бы выкарыстаць:

find . | grep \.jpg | perl -ne 'chop; print "$_\0"' | xargs -0  ls

(Заўвага: Для фільтрацыі я аддаю перавагу больш лёгкія для запамінання «| Grep» сінтаксіс «ФАЙНД» --name аргументаў.)

0
дададзена