তাদের সামগ্রীতে 100% নুল অক্ষরযুক্ত ফাইলগুলি কীভাবে সন্ধান করবেন?


16

লিনাক্স কমান্ড-লাইন কমান্ডটি এমন ফাইলগুলি সনাক্ত করতে পারে?

AFAIK findকমান্ড (বা grep) কেবলমাত্র টেক্সট ফাইলের ভিতরে একটি নির্দিষ্ট স্ট্রিংয়ের সাথে মেলে । কিন্তু আমি পুরো বিষয়বস্তু মেলে চাই, অর্থাত আমি দেখতে যা ফাইল রেগুলার এক্সপ্রেশন মেলে চান \0+, লাইন শেষ অক্ষর (গুলি) উপেক্ষা । হয়তো এই find . cat | grepআইডিয়মটি কাজ করতে পারে, তবে আমি কীভাবে গ্রেপ উপেক্ষা করার লাইনগুলি তৈরি করতে পারি না (এবং ফাইলটিকে বাইনারি হিসাবে গণ্য করব)।

পটভূমি: প্রতি কয়েকদিন পরে, যখন আমার ল্যাপটপ হিমশীতল হয়, আমার বিটিআরএফএস পার্টিশনটি তথ্য হারাতে থাকে: লেখার জন্য খোলা ফাইলগুলি তাদের বিষয়বস্তুগুলি শূন্যের সাথে প্রতিস্থাপন করে (ফাইলটির আকার আরও কম-বেশি অক্ষত থাকে)। আমি সিঙ্ক্রোনাইজেশন ব্যবহার করি এবং আমি এই নকল ফাইলগুলি প্রচার করতে চাই না: সেগুলি সনাক্ত করার জন্য আমার একটি উপায় প্রয়োজন যাতে আমি তাদের ব্যাকআপ থেকে ধরতে পারি।


আপনি বোঝাতে চান ফাইলগুলিতে সংখ্যা শূন্য রয়েছে?
রাহুল পাতিল

2
আমি মনে করি এটি সংখ্যা শূন্যের চেয়ে নুল অক্ষর সম্পর্কে।
gertvdijk

10
এখানে একটি পদক্ষেপ ফিরে নেওয়া যাক। প্রতি কয়েকদিন পরে, যখন আপনার ল্যাপটপ জমে যায়? কেন আমরা ঠিক করতে চেষ্টা করা হয় না যে এখানে, বাস্তব সমস্যা?
D_Bye

2
@ ডি_বাই এটি ভাল ধারণা, তবে এখনও পর্যন্ত এটি খুব বেশি দূরে আসেনি: [ ইউনিক্স.স্ট্যাকেক্সেঞ্জারজিও
অ্যাডাম রাইজকোভস্কি

1
তোমরা কি ভেবে দেখেছ -v255 কোনো বাইট 1 আছে সব ফাইল খুঁজে ফিল্টার: grep করার বিকল্প
Ctrl-Alt-delor

উত্তর:


10

grepপার্ল রেজেক্স মোড ব্যবহার করে আপনি ␀ অক্ষরের জন্য পারেন :

$ echo -ne "\0\0" > nul.bin
$ echo -ne "\0x\0" > non-nul.bin
$ grep -P "[^\0]" *.bin
Binary file non-nul.bin matches

সুতরাং আপনি এটি ব্যবহার করতে পারেন:

for path in *.foo
do
    grep -P "[^\0]" "$path" || echo "$path"
done

আমি অপ্রত্যাশিত ফলাফল পেয়েছি GNU grep 2.5.4। যাই হোক না কেন আমি ব্যবহার করি --binary-files=textবা না --binary-files=binary, এটি trueসমস্ত খালি ডেটা মানগুলির জন্য ফলাফল দেয় , যেমন। "\0\0", "\0x\0", "abcd"... সঠিক কোড আমি ব্যবহার করা হয়: for typ in binary text ;do for dat in '\0\0' '\0x\0' 'abcd' '' ;do printf "$dat" >f; grep --binary-files=$typ -P '[^\0]' f >/dev/null && echo true || echo false; done; done
Peter.O

1
আমি এখন আরও চেষ্টা করেছি GNU grep) 2.10। এই পরবর্তী সংস্করণটি প্রত্যাশিত ফলাফল দেয় ... সুতরাং, একটি
বিলেট

1
তার সাথে printf '\0\n\0\0\n\n' > fileবা এটির printf '\n' > fileজন্য তৈরি করা কোনও ফাইল ব্যর্থ হয় ।
স্টাফেন চেজেলাস

2
@ স্টাফেনচাজেলা ওপি "লাইনের শেষ চরিত্র (গুলি) উপেক্ষা করে বলেছিলেন"। সুতরাং কেবলমাত্র \0এবং \nঅক্ষর (উভয়ের শূন্য এমনকি) সমন্বিত যে কোনও ফাইলই মিলবে।
l0b0

6

আমি ডি_বাই সমস্যার মূল আবিষ্কার সম্পর্কে যা বলে তার সাথে আমি একমত।

যাইহোক কোনও ফাইলের মধ্যে কেবল \0এবং / অথবা \nআপনি ব্যবহার করতে পারেন কিনা তা পরীক্ষা করে দেখুন tr:

<file tr -d '\0\n' | wc -c

যা নাল / নিউলাইন এবং খালি ফাইলের জন্য 0 প্রদান করে।


2
tr -d '\0\n'নিউলাইন ইস্যুটি সমাধান করে, যা কেবলমাত্র আউটপুটে তালিকাভুক্ত খালি ফাইলগুলির ইস্যু (?) ছেড়ে দেয় ... এটি প্রতিটি ফাইলের প্রতিটি বাইট প্রক্রিয়া করে (যদিও এটি সমস্যা হতে পারে বা নাও হতে পারে) +1
পিটার.ও

@ পিটার.ও: নতুন লাইনের প্রয়োজনীয়তাটি আমি মিস করেছি, আপনাকে ধন্যবাদ। এই সমাধানটি খুব অনুকূলিত হয় না এবং যদি এটি প্রচুর ডেটাতে চালিত হয় তবে এটি একটি সমাধানের সাথে আরও ভাল হবে যে কোনও মিল না করে বাইটগুলি সন্ধান করার পরে চলে on
থোর

এটি খুব ভাল কাজ করে। আমি আমার ক্ষেত্রে আমাকে কেবল শূন্য দৈর্ঘ্যের ফাইলগুলি বাদ দেওয়ার বিষয়টি নিশ্চিত করতে হয়েছিল। ধন্যবাদ.
অ্যাডাম রাইজকোভস্কি

1
এটি অবশ্য নতুন খালি ফাইলগুলিকে "খালি" হিসাবে গণনা করবে।
ক্রিস ডাউন

1
@ ক্রিসডাউন: আমি উত্তর পাঠ্যটি কী করে তা পরিষ্কার করে দিয়েছি। এটি কেবল স্পষ্ট নয় যে ওপি নতুন লাইন-কেবলমাত্র ফাইলগুলি কী করতে চায়।
থোর

5

আমার সন্দেহ হয় যে এই ফাইলগুলি খুব কমই রয়েছে, তাদের কাছে কোনও ডিস্কের স্থান বরাদ্দ নেই, তারা কেবল একটি ফাইলের আকার নির্দিষ্ট করে ( duতাদের জন্য 0 প্রতিবেদন করবে)।

কোন ক্ষেত্রে, জিএনইউ সন্ধানের সাহায্যে আপনি এটি করতে পারেন (ধরে নেই কোনও ফাইল পাথে নতুন লাইনের অক্ষর রয়েছে):

find . -type f -size +0 -printf '%b:%p\n' | grep '^0:' | cut -d: -f2-

ভাল যুক্তি. আমি কখনই এ নিয়ে ভাবিনি। আমি চেষ্টা করবো. ব্যবহার করা duফাইল সিস্টেমে প্রতিটি একক ফাইলের বিষয়বস্তু স্ক্র্যাচ করা থেকে রোধ করবে, সুতরাং সম্পূর্ণ পদ্ধতিটি শেষ হতে 30+ মিনিট সময় নেয় না।
অ্যাডাম রাইজকোভস্কি

(এবং printf %bউপরের রিপোর্টগুলি কী রিপোর্ট duকরবে)
স্টাফেন চেজেলাস

আমি পরিবর্তন হবে -size +0থেকে -size +1তাই শূন্য দৈর্ঘ্য ফাইল ফলাফল থেকে বাদ দেওয়া হয়। এছাড়াও \nতাদের পথে থাকা ফাইলগুলি এই কমান্ডের জন্য সমস্যা সৃষ্টি করবে।
টাইসন

@ টাইসন -size +00 টির চেয়ে বেশি -size +1আকারের আকারের জন্য 512 এর চেয়ে বেশি আকারের আকারের হবে The নতুন লাইনের সীমাবদ্ধতা ইতিমধ্যে উল্লেখ করা হয়েছিল।
স্টাফেন চেজেলাস

@ স্টাফেনচাজেলাস আমাকে সম্পর্কে আলোকিত করার জন্য ধন্যবাদ -size +1, আপনি সত্যই সঠিক। আমি আমার উত্তর স্থির করেছি । :-)
টাইসন

4

এটি একটি ছোট অজগর প্রোগ্রাম এটি করতে পারে:

import sys

def only_contains_nulls(fobj, chunk_size=1024):
    first = True
    while True:
        data = fobj.read(chunk_size)
        if not data:
            if first:
                return 1  # No data
            else:
                return 0
        if data.strip("\0"):
            return 1
        first = False

if __name__ == '__main__':
    with open(sys.argv[1]) as f:
        sys.exit(only_contains_nulls(f))

এবং কর্মে:

$ printf '\0\0\0' > file
$ ./onlynulls file && echo "Only nulls" || echo "Non-null characters"
Only nulls
$ printf a >> file
$ ./onlynulls file && echo "Only nulls" || echo "Non-null characters"
Non-null characters

আপনাকে খুঁজে এর ব্যবহার করে একাধিক ফাইল পরীক্ষা করতে পারবেন -exec, xargs, গনুহ parallel, এবং অনুরূপ প্রোগ্রাম। বিকল্পভাবে, এটি ফাইল নামগুলি মুদ্রণ করবে যা মোকাবেলা করা দরকার:

files=( file1 file2 )
for file in "${files[@]}"; do
    ./onlynulls "$file" || printf '%s\n' "$file"
done

মনে রাখবেন যে আপনি যদি এই প্রোগ্রামটির ফলাফল অন্য কোনও প্রোগ্রামে পৌঁছে দিতে যাচ্ছেন তবে ফাইলের নামগুলিতে নতুন লাইন থাকতে পারে, তাই আপনার এটি আলাদাভাবে (যথাযথভাবে, সহ \0) সীমাবদ্ধ করা উচিত ।

আপনার যদি অনেকগুলি ফাইল থাকে তবে সমান্তরাল প্রক্রিয়াকরণের জন্য বিকল্পটি ব্যবহার করা ভাল since কারণ এটি একবারে কেবল একটি ফাইল পড়ে।


2
সাবধান, শূন্য দৈর্ঘ্য ফাইল (যেমন: /etc/nologin, ~/.hushlogin, .nomedia, ...) এই উত্তর দ্বারা ভুল শনাক্ত করা হয়।
টাইসন

@ টাইসন এটি নির্দেশ করার জন্য ধন্যবাদ! আমি ঠিক এটা ঠিক করেছি।
ক্রিস ডাউন

3

কেবল নাল-অক্ষর '\ 0' এবং নিউলাইন অক্ষর '\ n' রয়েছে এমন ফাইলগুলি সন্ধান করুন। মধ্যে sed কারণ প্রতিটি ফাইল একটি লাইন যে কোন অ নাল চরিত্র খোঁজার পরে অবিলম্বে প্রস্থান করার জন্য অনুসন্ধান করুন।
q

find -type f -name 'file-*' |
  while IFS= read -r file ;do 
      out=$(sed -n '1=; /^\x00\+$/d; i non-null
                      ; q' "$file")
      [[ $out == "1" ]] &&  echo "$file"
  done

পরীক্ষার ফাইল তৈরি করুন

> file-empty
printf '%s\n' 'line1' 'line2' 'line3'      > file-with-text           
printf '%4s\n' '' '' xx | sed 's/ /\x00/g' > file-with-text-and-nulls
printf '%4s\n' '' '' '' | sed 's/ /\x00/g' > file-with-nulls-and-newlines
printf '%4s'   '' '' '' | sed 's/ /\x00/g' > file-with-nulls-only

আউটপুট

./file-with-nulls-and-newlines
./file-with-nulls-only

হয় তর্কটি -print0অনুপস্থিত মনে হচ্ছে findবা IFS=অংশটি গণ্ডগোল হয়েছে। উদ্দিষ্ট সীমানা কী ছিল?
টাইসন

3

এই এক-লাইনের ব্যবহার গনুহ 100% nul ফাইল খুঁজে পেতে সবচেয়ে কার্যকর উপায় find, xargsএবং grep(আধুনিক অভিমানী PCRE সমর্থনে নির্মিত হয়):

find . -type f -size +0 -readable -print0 |
  LC_ALL=C xargs -r0 grep -LP "[^\x00]" --

অন্যান্য প্রদত্ত উত্তরের চেয়ে এই পদ্ধতির সুবিধাগুলি হ'ল:

  • অ-স্পার্স ফাইলগুলি অনুসন্ধানে অন্তর্ভুক্ত করা হয়।
  • Permission deniedসতর্কতা এড়িয়ে পঠনযোগ্য ফাইলগুলি গ্রেপের হাতে দেওয়া হয় না ।
  • grepকোনও নন-নুল বাইট খুঁজে পাওয়ার পরে ফাইলগুলি থেকে ডেটা পড়া বন্ধ হবে ( LC_ALL=Cপ্রতিটি বাইটকে একটি অক্ষর হিসাবে ব্যাখ্যা করা হয়েছে তা নিশ্চিত করার জন্য ব্যবহৃত হয় )।
  • খালি ফাইল (শূন্য বাইট) ফলাফলগুলিতে অন্তর্ভুক্ত নয়।
  • কম grepপ্রক্রিয়া দক্ষতার সাথে একাধিক ফাইল চেক করে।
  • নিউলাইনগুলি ধারণ করে বা শুরু করা পাথগুলি -সঠিকভাবে পরিচালনা করা হয়।
  • পাইথন / পার্লের অভাবযুক্ত বেশিরভাগ এম্বেড থাকা সিস্টেমে কাজ করে।

-Zবিকল্পটি পাস করা grepএবং ব্যবহার করা xargs -r0 ...100% নুল ফাইলগুলিতে (যেমন: ক্লিনআপ) আরও ক্রিয়া সম্পাদনের অনুমতি দেয়:

find . -type f -size +0 -readable -print0 |
  LC_ALL=C xargs -0 grep -ZLP "[^\x00]" -- |
  xargs -r0 rm --

আমি নিম্নলিখিত সিমলিঙ্কগুলি এড়াতে এবং ফাইল সিস্টেমে ট্র্যাভারিং এড়াতে (যেমন: দূরবর্তী মাউন্টগুলি, ডিভাইস ট্রি, বাঁধার মাউন্টগুলি ইত্যাদি) ব্যবহার করার জন্যও findবিকল্পগুলি ব্যবহার করার পরামর্শ দিচ্ছি ।-P-xdev

লাইন শেষের চরিত্র (গুলি) উপেক্ষা করার জন্য , নিম্নলিখিত রূপটি কাজ করা উচিত (যদিও আমি মনে করি এটি এত ভাল ধারণা নয়):

find . -type f -size +0 -readable -print0 |
  LC_ALL=C xargs -r0 grep -LP "[^\x00\r\n]" --

অযাচিত ফাইলগুলি (100% নুল / নিউলাইন অক্ষর) অপসারণ সহ এগুলি একসাথে রাখা:

find -P . -xdev -type f -size +0 -readable -print0 |
  LC_ALL=C xargs -0 grep -ZLP "[^\x00\r\n]" -- |
  xargs -0 rm --

আমি খালি ফাইল (শূন্য বাইট) অন্তর্ভুক্ত করার প্রস্তাব দিই না, তারা প্রায়শই খুব নির্দিষ্ট উদ্দেশ্যে উপস্থিত থাকে


এতগুলি বিকল্পের মধ্যে দ্রুততম হওয়া একটি সাহসী দাবি। আপনি যদি একটি মানদণ্ড যোগ করেন তবে আমি আপনার উত্তরটিকে স্বীকৃত হিসাবে চিহ্নিত করব :-)
অ্যাডাম রাইজকোভস্কি

এই ধরনের একটি মানদণ্ড বিভিন্ন ডিস্ক সাবসিস্টেমগুলির কার্যকারিতা সহ অনেকগুলি বিষয়ের উপর নির্ভরশীল।
টাইসন

অবশ্যই, কিন্তু কিছুই কিছুই চেয়ে ভাল। বিভিন্ন পন্থা সিপিইউর ব্যবহারকে আলাদাভাবে অনুকূল করে তোলে, তাই এটি এসএসডি বা এমনকি ক্যাশেড ফাইলগুলিতে বেনমার্ক করে তোলে। আপনি বর্তমানে যে মেশিনটিতে কাজ করছেন তার মেশিনটি ধরুন, এটি যা বাক্যটি লিখুন (সিপিইউ টাইপ, কোরগুলির কোনও নয়, র‌্যাম, হার্ড ড্রাইভের ধরণ), ফাইল সেটটি বর্ণনা করুন (উদাহরণস্বরূপ কার্নেল সোর্স ক্লোন + 1 জিবি ফাইল এতে \0900MB গর্তযুক্ত) এবং ফলাফল উপস্থিত সময়। আপনি যদি এটি এমনভাবে করেন যে মানদণ্ডটি আপনার জন্য বিশ্বাসযোগ্য, তবে এটি সম্ভবত আমাদের সকলের জন্য বিশ্বাসী হবে
অ্যাডাম রাইজকোভস্কি

"বেশিরভাগ এম্বেড থাকা সিস্টেমগুলি" এর GNU ইউটিলিটি নেই। ব্যস্তবক্স বেশী সম্ভবত।
স্টাফেন চেজেলাস

-Pডিফল্ট হয় find। আপনি যদি সিমলিংকগুলি অনুসরণ করতে চান তবে এটি -L/ -follow। আপনি দেখতে পাবেন যে পসিএক্স এমনকি সেই বিকল্পটি নির্দিষ্ট করে না find(যদিও পসিক্স হ'ল যারা কয়েকটি আদেশের জন্য -P / -H / -L প্রবর্তন করেছিলেন)।
স্টাফেন চেজেলাস

0

জিএনইউ সেড ব্যবহারের জন্য আপনি -zবিকল্পটি ব্যবহার করতে পারেন যা শূন্য-সমাপ্ত স্ট্রিং হিসাবে একটি লাইনকে সংজ্ঞায়িত করে এবং এর মতো খালি রেখাগুলি মুছতে এবং মুছতে:

if [ "$( sed -z '/^$/d' "$file" | head -c 1 | wc -c )" -eq 0 ]; then
    echo "$file contains only NULL!"
fi

অভ্যন্তরীণ হেড কমান্ডটি কেবল একটি অপ্টিমাইজেশন।


-1

পাইথন

ফাইল

ওরফে সংজ্ঞা দাও:

alias is_binary="python -c 'import sys; sys.exit(not b\"\x00\" in open(sys.argv[1], \"rb\").read())'"

এটা পরীক্ষা করো:

$ is_binary /etc/hosts; echo $?
1
$ is_binary `which which`; echo $?
0

একাধিক ফাইল

পুনরাবৃত্তভাবে সমস্ত বাইনারি ফাইলগুলি সন্ধান করুন:

IS_BINARY='import sys; sys.exit(not b"\x00" in open(sys.argv[1], "rb").read())'
find . -type f -exec bash -c "python -c '$IS_BINARY' {} && echo {}" \;

সমস্ত নন-বাইনারি ফাইলগুলি সন্ধান করতে এর &&সাথে পরিবর্তন করুন ||


1
প্রশ্ন ধারণকারী ফাইল চিহ্নিত করতে বলা শুধুমাত্র nul অক্ষর (উপেক্ষা নতুন লাইন), এখানে দেওয়া শনাক্ত ধারণকারী ফাইল পাইথন কোড কোন nul অক্ষর।
টাইসন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.