सभी "नॉन-बाइनरी" फाइल्स ढूंढना


43

क्या findकिसी निर्देशिका में सभी "गैर-बाइनरी" फाइलों को खोजने के लिए कमांड का उपयोग करना संभव है ? यहाँ समस्या मैं हल करने की कोशिश कर रहा हूँ।

मुझे विंडोज़ उपयोगकर्ता से फाइलों का एक संग्रह मिला है। इस संग्रह में स्रोत कोड और छवि फ़ाइलें हैं। हमारी बिल्ड सिस्टम उन फ़ाइलों के साथ अच्छा नहीं खेलती है जिनकी विंडो लाइन एंडिंग है। मेरे पास एक कमांड लाइन प्रोग्राम ( flip -u) है जो * निक्स और विंडो के बीच लाइन एंडिंग को फ्लिप करेगा। इसलिए, मैं ऐसा कुछ करना चाहूंगा

find . -type f | xargs flip -u

हालाँकि, यदि यह कमांड किसी छवि फ़ाइल, या अन्य बाइनरी मीडिया फ़ाइल के विरुद्ध चलाया जाता है, तो यह फ़ाइल को दूषित कर देगा। मुझे लगता है कि मैं फ़ाइल एक्सटेंशन की सूची बना सकता हूं और उसके साथ फ़िल्टर कर सकता हूं, लेकिन मेरे पास कुछ ऐसा होगा जो उस सूची को अद्यतित रखने में मुझ पर निर्भर न हो।

तो, क्या एक निर्देशिका ट्री में सभी गैर-बाइनरी फ़ाइलों को खोजने का एक तरीका है? या क्या कोई वैकल्पिक समाधान है जिस पर मुझे विचार करना चाहिए?


1
आप fileअपनी स्क्रिप्ट / पाइपलाइन में कहीं न कहीं उपयोगिता का उपयोग करके यह पहचान सकते हैं कि फ़ाइल डेटा है या टेक्स्ट
lk-

1
गैर-बाइनरी से आपका क्या मतलब है (आधुनिक कंप्यूटर पर सब कुछ बाइनरी है)। मैं अनुमान लगा रहा हूं कि आप पुराने C / PM ऑपरेटिंग सिस्टम से अंतर का उपयोग कर रहे हैं, जिसमें टेक्स्ट और बाइनरी फाइलें थीं। टेक्स्ट फाइलें किसी भी लम्बाई की हो सकती हैं, लेकिन इसे ctrl-z के साथ समाप्त करना पड़ता है, और बाइनरी फ़ाइलों को 512byx ब्लॉक के कई होना चाहिए। यदि ऐसा है तो आप टेक्स्ट फाइल अर्थ हैं। (मैं यह भी ध्यान देता हूं कि आप गैर-बाइनरी फ़ाइलों में समाप्त होने वाली रेखा के बारे में लिखते हैं, यह भी सुझाव देगा कि वे पाठ फ़ाइलें हैं) क्या यह सही है?
ctrl-alt-delor-

सभी फाइलें बाइनरी हैं, यह सिर्फ व्याख्या का एक मेटर है। क्या आप पाठ फ़ाइलों को खोजने के लिए पूछ रहे हैं?
ctrl-alt-delor

@richard मैं एक युग में जहाँ हम सादे-पाठ के रूप में व्याख्या की जा करने के लिए होती फ़ाइलों कहा जाता है आ सादा पाठ , और अन्य सभी फ़ाइलें (छवियों, वर्ड प्रोसेसिंग डॉक्स, आदि) द्विआधारी। मैं इसके सभी एक और शून्य को हूड के तहत जानता हूं :)
एलन स्टॉर्म

1
आह, मैं देखता हूं कि आप मेरी शर्तों के बारे में क्या सोचते हैं - भ्रम से बचने के लिए मैं भविष्य में बाइनरी / टेक्स्ट का उपयोग करूंगा। पुन: \ r \ n बात - इसकी मेरी समझ उन ASCII वर्णों के लिए एक टाइपराइटर की गाड़ी वापसी (लाइन की शुरुआत में) और लाइन फीड (एक लाइन नीचे ले जाने) के लिए है। इसलिए \ r \ n वास्तविक विश्व भौतिक चीज़ का एक "अधिक सटीक" मॉडल है जो रेखा वर्ण का अंत था। पूर्व OS X, Macs ने इसके लिए सिर्फ a \ r का उपयोग किया। मैं आम तौर पर पूरी बात लिखता हूं "मनमाने ढंग से पसंद की गई एक भीड़ में जो हम अभी भी साथ काम कर रहे हैं"
एलन स्टॉर्म

जवाबों:


20

मैं fileग्रिप या awk में आउटपुट का उपयोग टेक्स्ट फ़ाइलों को खोजने के लिए करता हूं , फिर fileआउटपुट और पाइप के फ़ाइल नाम को एक्सरे में निकालता हूं।

कुछ इस तरह:

file * | awk -F: '/ASCII text/ {print $1}' | xargs -d'\n' -r flip -u

ध्यान दें कि grep किसी भी 'पाठ' के बजाय 'ASCII पाठ' की खोज करता है - आप शायद रिच टेक्स्ट दस्तावेज़ों या यूनिकोड पाठ फ़ाइलों आदि के साथ गड़बड़ नहीं करना चाहते हैं।

findफ़ाइलों की सूची बनाने के लिए आप (या जो भी) उपयोग कर सकते हैं file:

find /path/to/files -type f -exec file {} + | \
  awk -F: '/ASCII text/ {print $1}' | xargs -d'\n' -r flip -u

-d'\n'Xargs का तर्क xargs को प्रत्येक इनपुट लाइन को एक अलग तर्क के रूप में मानता है, इस प्रकार रिक्त स्थान और अन्य समस्याग्रस्त वर्णों के साथ फ़ाइल नाम के लिए खानपान। यानी यह के लिए एक विकल्प है xargs -0जब इनपुट स्रोत नहीं है या (जैसे शून्य से अलग की गई उत्पादन उत्पन्न नहीं कर सकते findके -print0विकल्प)। चैंजोग के अनुसार, सिपाही 2005 में xargs -d/ --delimiterविकल्प मिला, इसलिए किसी भी गैर-प्राचीन linux distro में होना चाहिए (मुझे यकीन नहीं था, यही कारण है कि मैंने जाँच की - मुझे बस याद है कि यह "हाल ही में" जोड़ था)।

ध्यान दें कि फ़ाइल नाम में एक लाइनफ़ीड एक मान्य चरित्र है, इसलिए यदि कोई फ़ाइल नाम उन में फीडफ़ीड है तो यह टूट जाएगा। विशिष्ट यूनिक्स उपयोगकर्ताओं के लिए, यह पथिक रूप से पागल है, लेकिन अगर मैक या विंडोज मशीनों पर फ़ाइलों की उत्पत्ति हुई है तो यह अनसुना नहीं है।

यह भी ध्यान दें कि fileसही नहीं है। यह एक फ़ाइल में डेटा के प्रकार का पता लगाने में बहुत अच्छा है, लेकिन कभी-कभी भ्रमित हो सकता है।

मैंने सफलता के साथ अतीत में कई बार इस पद्धति के कई रूपों का उपयोग किया है।


1
इस समाधान के लिए धन्यवाद! मेरे सोलारिस सिस्टम के बजाय किसी कारण से fileप्रदर्शित English textहोता है ASCII text, इसलिए मैंने उस हिस्से को तदनुसार संशोधित किया। इसके अलावा, मैंने awk -F: '{print $1}'समकक्ष के साथ प्रतिस्थापित किया cut -f1 -d:
एंड्रयू चेयोंग

3
grep -Iफिल्टर बायनेरिज़ के लायक
xenoterracide

शब्द की तलाश textपर्याप्त होनी चाहिए। यह भी लेने होंगे fileजैसे विवरण ASCII Java program textया HTML document textया troff or preprocessor input text
user1024

मेरा उत्तर आंशिक रूप से इस उत्तर पर प्रतिक्रिया / सुधार है। ASCII textआरटीएफ में गड़बड़ी से बचने के लिए ग्रेपिंग के बारे में बहुत अच्छी बात ।
वाइल्डकार्ड

1
xenoterracide: आपने मेरे जीवन को बचाया! बस एक झंडा -I और बिंगो
सर्जियो

9

नहीं। बाइनरी या गैर-बाइनरी फ़ाइल के बारे में कुछ खास नहीं है। आप '0x01-0x7F में केवल वर्ण सम्‍मिलित हैं' जैसे अनुमानों का उपयोग कर सकते हैं, लेकिन वह गैर-ASCII वर्णों वाली बाइनरी फ़ाइलों और अनलकी बाइनरी फ़ाइलों वाली पाठ फ़ाइलों के साथ पाठ फ़ाइलों को कॉल करेगा।

अब, एक बार आपने अनदेखा कर दिया है कि ...

ज़िप फ़ाइलें

यदि यह आपके विंडोज यूजर से जिप फाइल के रूप में आ रहा है, तो जिप फॉर्मेट आर्काइव में ही बाइनरी या टेक्स्ट के रूप में मार्किंग फाइल्स को सपोर्ट करता है। -aइस पर ध्यान देने और परिवर्तित करने के लिए आप अनज़िप के विकल्प का उपयोग कर सकते हैं । बेशक, इसके लिए पहला पैराग्राफ देखें कि यह एक अच्छा विचार क्यों नहीं हो सकता है (ज़िप प्रोग्राम ने संग्रह को बनाते समय गलत अनुमान लगाया हो सकता है)।

zipinfo आपको बताएगा कि इसकी zipfile लिस्टिंग में कौन सी फाइलें बाइनरी (b) या टेक्स्ट (t) हैं।

अन्य फ़ाइलें

फ़ाइल कमांड एक फ़ाइल को देखेगा और इसे पहचानने का प्रयास करेगा। विशेष रूप से, आपको संभवतः इसका -i(आउटपुट MIME प्रकार) विकल्प उपयोगी लगेगा ; केवल टाइप पाठ / * के साथ फ़ाइलों को परिवर्तित


6

में केवल प्रक्रिया गैर बाइनरी फ़ाइलें करने के लिए एक सामान्य समाधान bashका उपयोग कर file -b --mime-encoding:

while IFS= read -d '' -r file; do
  [[ "$(file -b --mime-encoding "$file")" = binary ]] &&
    { echo "Skipping   $file."; continue; }

  echo "Processing $file."

  # ...

done < <(find . -type f -print0)

मैंने फ़ाइल उपयोगिता के लेखक से संपर्क किया और उन्होंने -005.26 संस्करण में एक निफ्टी पैरामेटर जोड़ा (2016-04-16 को जारी किया गया, उदाहरण के लिए वर्तमान आर्क और उबंटू 16.10 में है) जो file\0result\0एक ही बार में इसे खिलाया गया कई फ़ाइलों के लिए प्रिंट करता है, इस तरह से आप कर सकते हैं उदाहरण के लिए:

find . -type f -exec file -00 --mime-encoding {} + |
  awk 'BEGIN{ORS=RS="\0"}{if(NR%2)f=$0;else if(!/binary/)print f}' | 

( awkभाग गैर-बाइनरी नहीं है हर फ़ाइल को फ़िल्टर करने के लिए ORSहै। आउटपुट विभाजक है।)

एक लूप में भी इस्तेमाल किया जा सकता है:

while IFS= read -d '' -r file; do

  echo "Processing $file."

  # ...

done < <(find . -type f -exec file -00 --mime-encoding {} + |
  awk 'BEGIN{ORS=RS="\0"}{if(NR%2)f=$0;else if(!/binary/)print f}')

इसके आधार पर और पिछले मैंने bashबाइनरी फ़ाइलों को फ़िल्टर करने के लिए एक छोटी सी स्क्रिप्ट बनाई, जो इसके नए संस्करणों में -00पैरामीटर का उपयोग करके नई विधि का उपयोग करती fileहै और पुराने संस्करणों पर पिछले पद्धति पर वापस आती है:

#!/bin/bash

# Expects files as arguments and returns the ones that do
# not appear to be binary files as a zero-separated list.
#
# USAGE:
#   filter_binary_files.sh [FILES...]
#
# EXAMPLE:
#   find . -type f -mtime +5 -exec ./filter_binary_files.sh {} + | xargs -0 ...
# 

[[ $# -eq 0 ]] && exit

if [[ "$(file -v)" =~ file-([1-9][0-9]|[6-9]|5\.([3-9][0-9]|2[6-9])) ]]; then
  file -00 --mime-encoding -- "$@" |
    awk 'BEGIN{ORS=RS="\0"}{if(NR%2)f=$0;else if(!/binary/)print f}'
else
  for f do
    [[ "$(file -b --mime-encoding -- "$f")" != binary ]] &&
      printf '%s\0' "$f"
  done
fi

या यहाँ एक और POSIX-y एक, लेकिन इसके लिए समर्थन की आवश्यकता है sort -V:

#!/bin/sh

# Expects files as arguments and returns the ones that do
# not appear to be binary files as a zero-separated list.
#
# USAGE:
#   filter_binary_files.sh [FILES...]
#
# EXAMPLE:
#   find . -type f -mtime +5 -exec ./filter_binary_files.sh {} + | xargs -0 ...
# 

[ $# -eq 0 ] && exit

if [ "$(printf '%s\n' 'file-5.26' "$(file -v | head -1)" | sort -V)" = \
    'file-5.26' ]; then
  file -00 --mime-encoding -- "$@" |
    awk 'BEGIN{ORS=RS="\0"}{if(NR%2)f=$0;else if(!/binary/)print f}'
else
  for f do
    [ "$(file -b --mime-encoding -- "$f")" != binary ] &&
      printf '%s\0' "$f"
  done
fi

6

स्वीकृत उत्तर मेरे लिए उन सभी को नहीं मिला। यहाँ एक उदाहरण है grep का उपयोग -Iबायनेरिज़ को अनदेखा करने के लिए, और सभी छिपी हुई फ़ाइलों को अनदेखा करने के लिए ...

find . -type f -not -path '*/\.*' -exec grep -Il '.' {} \; | xargs -L 1 echo 

यहाँ यह एक व्यावहारिक अनुप्रयोग में उपयोग में है: dos2unix

https://unix.stackexchange.com/a/365679/112190


4

कैस का जवाब अच्छा है, लेकिन यह समझे हुए फ़ाइलनाम को मानता है ; विशेष रूप से यह माना जाता है कि फ़ाइल नाम में नई सीमाएँ नहीं होंगी।

यहाँ इस धारणा को बनाने का कोई अच्छा कारण नहीं है, क्योंकि यह उस मामले को सही तरीके से संभालने के लिए काफी सरल है (और मेरी राय में वास्तव में क्लीनर):

find . -type f -exec sh -c 'file "$1" | grep -q "ASCII text"' sh {} \; -exec flip -u {} \;

findआदेश केवल का उपयोग करता है POSIX द्वारा निर्दिष्ट सुविधाओं-execबूलियन परीक्षणों के रूप में मनमाना कमांड चलाने के लिए उपयोग करना सरल है, मजबूत है (सही ढंग से विषम फ़ाइलनाम को संभालता है), और इससे अधिक पोर्टेबल है -print0

वास्तव में, कमांड के सभी हिस्सों को छोड़कर POSIX द्वारा निर्दिष्ट किया गया है flip

ध्यान दें कि fileयह वापस आने वाले परिणामों की सटीकता की गारंटी नहीं देता है। हालांकि, इसके आउटपुट में "ASCII टेक्स्ट" के लिए ग्रिपिंग अभ्यास काफी विश्वसनीय है।

(यह शायद कुछ पाठ फ़ाइलों को याद कर सकता है , लेकिन "ASCII पाठ" के रूप में एक द्विआधारी फ़ाइल को गलत तरीके से पहचानने की बहुत संभावना नहीं है और इसे mangle करता है - इसलिए हम सावधानी के साथ गलत कर रहे हैं।)


तर्क-कम फ़ाइल callsकाफी धीमी हो सकती है, उदाहरण के लिए वीडियो के लिए यह आपको एन्कोडिंग के बारे में सब कुछ बताएगा।
phk

इसके अलावा, आप मान रहे हैं कि कोई फ़ाइल शुरू नहीं होती है -
phk

और मुझे कोई कारण नहीं दिखता है कि आप सिर्फ एक कॉल क्यों नहीं करेंगे file, यह कई फाइलों को तर्क के रूप में ले सकता है।
phk

@phk, अपनी टिप्पणियों को संबोधित करने के लिए: (1) संभावित सुस्ती को जानना अच्छा है, लेकिन मैं इसे रोकने के लिए कोई पॉसिक्स तरीका नहीं देखता; (2) मैं फ़ाइल नामों के बारे में शून्य धारणा बनाता हूं , क्योंकि findकमांड ./शेल कमांड को दिए गए किसी फ़ाइल नाम के लिए उपसर्ग करेगा ; (३) एक समय में grepएक ही fileकमांड आउटपुट पर एक परीक्षण के रूप में उपयोग करना केवल एक ऐसा पॉसिक्स तरीका है जिससे मैं उन फ़ाइलनामों की सही हैंडलिंग की गारंटी देख सकता हूं जिनमें नईलाइन शामिल हो सकती हैं।
वाइल्डकार्ड

मैंने आपके अंतिम "POSIX-y" समाधान को देखा और मुझे लगता है कि यह चतुर है - लेकिन आप यह मानते हैं कि ध्वज और विभाजक fileका समर्थन करता है , जिनमें से कोई भी POSIX द्वारा गारंटीकृत नहीं है--mime-encoding--
वाइल्डकार्ड

2
find . -type f -exec grep -I -q . {} \; -print

यह -type fवर्तमान निर्देशिका (या नीचे) में सभी नियमित फाइलें ( ) पाएंगे जो grepसोचते हैं कि गैर-खाली और गैर-बाइनरी हैं।

यह grep -Iबाइनरी और गैर-बाइनरी फ़ाइलों के बीच अंतर करने के लिए उपयोग करता है। -Iझंडा और कारण होगा grepएक गैर शून्य बाहर निकलने की स्थिति के साथ बाहर निकलने के लिए जब यह पता लगाता है कि एक फ़ाइल बाइनरी है। एक "बाइनरी" फ़ाइल है, के अनुसार grep, एक फाइल जिसमें मुद्रण योग्य ASCII सीमा के बाहर चरित्र होता है।

-qविकल्प के लिए grepकरता है, तो दिए गए पैटर्न किसी भी डेटा उत्सर्जन के बिना, पाया जाता है यह एक शून्य से बाहर निकलें स्थिति के साथ छोड़ने के लिए कारण होगा। हमारे द्वारा उपयोग किया जाने वाला पैटर्न एक एकल बिंदु है, जो किसी भी वर्ण से मेल खाएगा।

यदि फ़ाइल गैर-बाइनरी पाई जाती है और यदि उसमें कम से कम एक वर्ण होता है, तो फ़ाइल का नाम मुद्रित होता है।

यदि आप बहादुर महसूस करते हैं, तो आप flip -uइसमें अपना प्लग भी लगा सकते हैं :

find . -type f -exec grep -I -q . {} \; -print -exec flip -u {} \;

1

इसे इस्तेमाल करे :

find . -type f -print0 | xargs -0 -r grep -Z -L -U '[^         -~]' | xargs -0 -r flip -u

जहां का तर्क grep '[^ -~]'है '[^<tab><space>-~]'

यदि आप इसे शेल कमांड लाइन पर टाइप करते हैं, तो पहले Ctrl+ टाइप करें । एक संपादक में, कोई समस्या नहीं होनी चाहिए।VTab

  • '[^<tab><space>-~]'किसी भी वर्ण से मेल खाएगा जो ASCII पाठ नहीं है (गाड़ी के रिटर्न की अनदेखी grep)।
  • -L केवल उन फ़ाइलों के नाम को प्रिंट करेगा जो मेल नहीं खाती हैं
  • -Zउत्पादन फ़ाइल नाम एक अशक्त चरित्र के साथ अलग हो जाएगा (के लिए xargs -0)

यह ध्यान देने योग्य है कि पर्ल जैसे रेगेक्स grep -P(यदि उपलब्ध हो) \tउपलब्ध है। वैकल्पिक रूप से, स्थानीय अनुवाद का उपयोग करते हुए यदि शेल इसका समर्थन करता है: $'\t'( bashऔर zshकरते हैं)।
phk

1

वैकल्पिक समाधान:

Dos2unix कमांड विंडोज सीआरएलएफ से यूनिक्स एलएफ तक लाइन एंडिंग को बदल देगा, और स्वचालित रूप से बाइनरी फाइलों को छोड़ देगा। मैं इसे पुनरावर्ती उपयोग करके लागू करता हूं:

find . -type f -exec dos2unix {} \;

चूँकि dos2unixकई फाइलनामों को तर्क के रूप में लिया जा सकता है, यह करने के लिए बहुत अधिक कुशल हैfind . -type f -exec dos2unix {} +
एन्थॉन सेप

0

sudo find / (-type f -and -path '* / git / *' -iname 'README') -exec grep -liI '100644 \ | 100755' {} \; -exec फ्लिप -u {} \;

i। -type f -and -path '* / git / *' -iname 'README'): नाम git वाले पथ के भीतर फाइलों की खोज करता है और README नाम के साथ फाइल करता है। यदि आप किसी विशिष्ट फ़ोल्डर और फ़ाइलनाम को खोजते हैं तो यह उपयोगी होगा।

ii.-exec कमांड फाइल द्वारा उत्पन्न फाइल नाम पर एक कमांड चलाता है

iii \। कमांड के अंत का संकेत देता है

iv। {} पिछले खोज खोज से मिली फ़ाइल / फ़ोल्डरनाम का आउटपुट है

v.Multiple आदेश बाद में चलाए जा सकते हैं। संलग्न करके -exec "कमांड" \; जैसे कि -exec फ्लिप -u \ के साथ;

vii.grep

1.-l lists the name of the file
2.-I searches only non-binary files
3.-q quiet output
4.'100644\|100755' searches for either 100644 or 100755 within the file found. if found it then runs flip -u. \| is the or operator for grep. 

आप इस परीक्षण निर्देशिका को क्लोन कर सकते हैं और इसे आज़मा सकते हैं: https://github.com/alphaCTzo7G/stackexchange/tree/master/linux/findSolution204092017

यहाँ और अधिक विस्तृत जवाब: https://github.com/alphaCTzo7G/stackexchange/blob/master/linux/findSolution204092017/README.md

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.