খুঁজে | xargs shasum নিজেই চেকসাম ফাইলের চেকসাম তৈরি করে (অকাল পূর্বে) এবং চেক করার সময় ব্যর্থ হয়


10

আমার সমস্যা (এর সাথে একটি স্ক্রিপ্টে #!/bin/sh) নিম্নরূপ: আমি সংরক্ষণাগার সংক্রান্ত উদ্দেশ্যে ডিরেক্টরিতে সমস্ত ফাইল চেকসাম করার চেষ্টা করি। সমস্ত ফাইলের নাম সহ চেকসাম (আমার ক্ষেত্রে sha1) ফাইলটি একই ডিরেক্টরিতে থাকা উচিত। বলুন আমাদের ~/testফাইল f1এবং f2: সহ একটি ডিরেক্টরি আছে ।

mkdir ~/test
cd ~/test
echo "hello" > f1
echo "world" > f2

এখন দিয়ে চেকসাম গণনা করা হচ্ছে

find -maxdepth 1 -type f -printf '%P\n' | xargs shasum

আমি যা চাই ঠিক তা করে, এটি কেবল বর্তমান ডিরেক্টরিটির সমস্ত ফাইল তালিকাভুক্ত করে এবং sha1 অঙ্কগুলি গণনা করে (ম্যাক্সডেপথ পরে পরিবর্তিত হতে পারে)। STDOUT এ আউটপুটটি হ'ল:

f572d396fae9206628714fb2ce00f72e94f2258f  f1
9591818c07e900db7e1e0bc4b884c945e6a61b24  f2

দুর্ভাগ্যক্রমে, যখন এটি কোনও ফাইলে সংরক্ষণ করার চেষ্টা করা হয়

find -maxdepth 1 -type f -printf '%P\n' | xargs shasum > sums.sha1

ফলস্বরূপ ফাইলটি নিজের জন্য চেকসাম প্রদর্শন করে:

da39a3ee5e6b4b0d3255bfef95601890afd80709  sums.sha1
f572d396fae9206628714fb2ce00f72e94f2258f  f1
9591818c07e900db7e1e0bc4b884c945e6a61b24  f2  

এবং অতএব পরে ব্যর্থ হয় shasum --check, কারণ শেষ অঙ্কটি সংরক্ষণের সময় অতিরিক্ত ফাইল পরিবর্তনের সুস্পষ্ট সমস্যার কারণে।

আমি চারপাশে এবং এর -pজন্য পতাকা ব্যবহার করে xargsজানতে পেরেছিলাম যে এটি ফাইন্ড কমান্ড কার্যকর করার আগে আউটপুট ফাইলটি তৈরি করে, তাই অতিরিক্ত ফাইলটি পাওয়া যায় এবং চেকসামড করা হবে ...

আমি জানি যে কর্মক্ষেত্র হিসাবে আমি চেকসামটি অন্য কোনও স্থানে (অস্থায়ী ডিরেক্টরি মাধ্যমে mktemp) সংরক্ষণ করতে পারি বা এটি সুনির্দিষ্টভাবে অনুসন্ধানে বাদ দিতে পারি, তবে আমি বুঝতে চাই যে এটি কেন এটির মতো আচরণ করে - যা আমার চোখে এটি কার্যকর নয়, উদাহরণস্বরূপ, যদি প্রথম কমান্ডটি আউটপুট ফাইলটি ইতিমধ্যে ডিস্কে রয়েছে কিনা তা পরীক্ষা করে দেখায়, এটি কখনই সঠিক উত্তর পাবে না ...


8
এটি নয় xargs, এটি নিজেই শেল যা এই ফাইলটি তৈরি করে, কারণ কোনও কমান্ড কার্যকর করার আগে শেল সমস্ত ইনপুট, আউটপুট এবং পাইপগুলি পুনর্নির্দেশ করে, যাতে findআউটপুট ফাইলটি শুরু হওয়ার আগেই উপস্থিত থাকে। -execপরিবর্তে ব্যবহার করুন:find -maxdepth 1 -type f -exec sh -c 'shasum "$@" > sums.sha1' {} +
jimmij

@ জিম্মিজ, বেশ কয়েকটি অনুরোধের shপ্রয়োজন হলে তা কাজ করার গ্যারান্টিযুক্ত নয় । নোট করুন যে আপনার জন্য $0আগে একটি যুক্তি প্রয়োজন {}
স্টাফেন চেজেলাস

@ জিম্মিজ আপনার অন্য উত্তর যে প্রস্তাবটি দিয়েছিল teeতা অদৃশ্য হয়ে গেছে? আমি এটি চেষ্টা করেছিলাম এবং এটি ঠিক কাজ করে, আমি যোগ করার সাথে STDOUT কেও দমন করেছি 1>/dev/null। উত্তরে কিছু ভুল ছিল নাকি এটি বাগ ছিল?
ব্যবহারকারী 121391

@ ব্যবহারকারী 121391 স্টিফেন উল্লেখ করেছিলেন যে কখনও কখনও রেসের অবস্থার সমস্যা হতে পারে, যা সত্য বলে মনে হয়। আমি এটি কিছুক্ষণের জন্য মুছে ফেলেছি যাতে আপনি দেখতে পারেন তবে তালিকায় আপনার অনেকগুলি ফাইল থাকলে সেই আদেশটি ভুল হতে পারে।
জিম্মিজ

@ জিম্মিজ আহ, আমি দেখছি আপনি যদি সমস্যাগুলি সম্পর্কে একটি সতর্কতা দিয়ে এটি উপসর্গ করেন তবে এটি সহায়ক হতে পারে, কারণ আমি মনে করি এটি এতটা সুপরিচিত নয় যে এটি ঘটতে পারে। অন্যথায়, আমি কেসগুলির জন্য আপনার উত্তরটি গ্রহণ করতাম যদি পুনরাবৃত্তি হওয়া রানগুলিতে পুরানো ফাইল এবং অ্যান্থনের ক্ষেত্রে এটির ওভাররাইট করা উচিত সেই ক্ষেত্রে অন্তর্ভুক্ত থাকে।
ব্যবহারকারী 121391

উত্তর:


12

আপনি xargsব্যবহার করে ফাইলটি পৌঁছতে বাধা দিতে পারেন :

find . -maxdepth 1 -type f ! -name sums.sha1 -printf '%P\n' |
  xargs -r shasum -- > sums.sha1

ফাঁকা বা নিউলাইন, কোটস বা ব্যাকস্ল্যাশ রয়েছে এমন ফাইলের নামের সমস্যা রোধ করতে আমি তবে ব্যবহার করব:

find . -maxdepth 1 -type f ! -name sums.sha1 -printf '%P\0' |
  xargs -r0 shasum -- > sums.sha1

পরিবর্তে.

--ফাইলের নাম যে দিয়ে শুরু সঙ্গে সমস্যা এড়াতে হয় -। তবে এটি কল করা কোনও ফাইলের জন্য সহায়তা করবে না -। আপনি যদি এর -print0পরিবর্তে ব্যবহার করেন তবে আপনার -printf '%P\0'প্রয়োজন --হবে না এবং -ফাইলটি নিয়ে কোনও সমস্যা হত না ।


আপনার সমাধানটি আমি ব্যবহার করে শেষ করেছি। আমি বিশেষত পছন্দ করি যে পরবর্তী রানগুলি চেকসাম ফাইলটি পুনরায় চাপিয়ে দেয় না এবং ডিরেক্টরিটি স্ফীত করে না। এছাড়াও, আমার স্ক্রিপ্টে আমি basenameপ্রদত্ত পুরো পথ থেকে sums.sha1 ফাইলের নামটি পেয়েছি (এটি প্রশ্নের মধ্যে অন্তর্ভুক্ত ছিল না তবে এটি অন্যকে সাহায্য করতে পারে)।
ব্যবহারকারী 121391

7

যেহেতু আপনি ব্যবহার করছেন -maxdepth 1, আমি ধরে নিচ্ছি আপনি পুনরাবৃত্তি চান না। যদি তা হয় তবে তার পরিবর্তে শেলের মধ্যে এটি করুন:

for f in ~/test/*; do
    shasum -- "$f"
done > sums.sha1

ডিরেক্টরিগুলি এড়িয়ে যেতে, আপনি এটি করতে পারেন:

for f in ~/test/*; do
    [ ! -d "$f" ] && shasum -- "$f"
done > sums.sha1

আপনার যদি পুনরাবৃত্তি প্রয়োজন হয় এবং ব্যবহার করছেন তবে bashকরুন:

shopt -s globstar
for f in ~/test/**; do
    [ ! -d "$f" ] && shasum -- "$f"
done > sums.sha1

নোট করুন যে এই সমস্ত পদ্ধতির স্পেস, নিউলাইনস বা অন্য যে কোনও কিছু রয়েছে এমন স্বেচ্ছাসেবী ফাইল নামগুলিতে কাজ করার সুবিধা রয়েছে।


আমি মনে করি আপনি উল্লেখ করবেন যে এটি ওপিতে যে কোনও সমস্যাগুলির সমাধান করতে পারে ফাইলগুলির নামগুলির সাথে তাদের মধ্যে নতুন লাইনের সাথেও। অন্যদিকে যদি sums.sha1ইতিমধ্যে সেখানে থাকে (পূর্ববর্তী রান থেকে) আপনার সমাধানটি এতে অন্তর্ভুক্ত করবে।
অ্যান্থন

দুঃখিত, আমি এর আগে পরিষ্কার করিনি: ম্যাক্সডেপথটি কেবলমাত্র এই উদাহরণে ব্যবহৃত হয়েছিল, আমি একটি ফাংশন ব্যবহার করি যেখানে ব্যবহারকারী / স্ক্রিপ্ট কোনও মান সরবরাহ করতে পারে, যদিও বর্তমানে আমার কেবল গভীরতা প্রয়োজন 1
ব্যবহারকারী 121391

@ ব্যবহারকারী 121391 পুনরাবৃত্ত পদ্ধতির জন্য আপডেট উত্তর দেখুন।
টেরডন

নোট করুন যে এটি পাইপ, ডিভাইস ... (এবং তাদের কাছে প্রতিলিঙ্ক) যেমন নিয়মিত অন্যান্য নিয়মিত ফাইলগুলি চেকসাম করার চেষ্টা করবে।
স্টাফেন চেজেলাস

আপনাকে ধন্যবাদ, ব্যক্তিগতভাবে আমি ব্যবহার করছি shতবে আপনার উত্তরটি অন্যকে সাহায্য করতে পারে।
ব্যবহারকারী 121391

4

সাথে zsh:

shasum -- *(D.) > sums.sha1

পুনঃনির্দেশটি তৈরি করার আগে গ্লোবটি প্রসারিত হবে, সুতরাং sums.sha1এটি প্রথম স্থানে না থাকলে অন্তর্ভুক্ত হবে না।

Dহ'ল ডট-ফাইল (লুকানো ফাইল) অন্তর্ভুক্ত করা find.কেবলমাত্র নিয়মিত ফাইল নির্বাচন করা (আপনার মতো -type f)।

sums.sha1যাইহোক এটি প্রথম স্থানে উপস্থিত থাকলে তা বাদ দিতে :

setopt extendedglob # best in ~/.zshrc
shasum -- ^sums.sha1(D.) > sums.sha1

মনে রাখবেন যে ওয়ান শসুম কমান্ডটি চালায় , সুতরাং তালিকাটি বিশাল হলে আপনি "আরগের তালিকা খুব দীর্ঘ" ত্রুটিটি দেখে শেষ করতে পারেন। যে চারপাশে কাজ করতে:

autoload zargs
zargs -e/ -- *(D.) / shasum > sums.sha1

কল করা কোনও ফাইলের সাথে সম্ভাব্য সমস্যা এড়াতে ./*পরিবর্তে আমি ব্যবহারের পরামর্শ দেব ।*-


আমি শেলের ধরণ দিয়ে প্রশ্নটি সম্পাদনা করেছি, তবে আপনার উত্তর আমাকে মনে করিয়ে দেয় যে আমি কিছুক্ষণ আগে zsh এ চলে যেতে চেয়েছিলাম ...;)
ব্যবহারকারী 121391

1

অন্যান্য উত্তরগুলি ইতিমধ্যে ইস্যুটি বলেছে যে শেলটি খোলে এবং sums.sha1ফাইলটি তৈরি করে , আপনার পাইপলাইনটি কার্যকর করার আগে। আপনি প্রোগ্রামটি ব্যবহার করতে পারেন spongeযা moreutilsঅনেক বিতরণের প্যাকেজের অংশ । শেল পুনর্নির্দেশের বিপরীতে spongeফাইলটি খোলার আগে, এটি সবকিছু না পাওয়া পর্যন্ত অপেক্ষা করা হবে। আপনি যখন একই পাইপলাইনে পড়া কোনও ফাইল লিখতে চান তখন এটি সাধারণত ব্যবহৃত হয়।

আপনার ক্ষেত্রে এটি ব্যবহার করা হয়:

$ find -maxdepth 1 -type f -printf '%P\n' |xargs shasum |sponge sums.sha1
$ cat sums.sha1
31836aeaab22dc49555a97edb4c753881432e01d  B
7d157d7c000ae27db146575c08ce30df893d3a64  A

0

বিকল্পের জন্য সন্ধান / জার্গস ইত্যাদির জন্য আপনি শ 1 ডিডিপ চাইবেন। এটি সম্ভবত অন্য কোনও প্যাকেজে রয়েছে - আমার বাক্সে এটি এমডি 5 ডিভিডি প্যাকেজে আসে।

অন্যরা যেমন বলেছে যে sums.sha1 সন্ধানের আগেই শেল দ্বারা তৈরি করা হয়। সাথে কাজ ! -name sums.sha1করার একটি কৌশল find, যেমন হবে

find -maxdepth 1 -type f -printf '%P\n' | xargs shasum | grep -v ' sums\.sha1$' > sums.sha1
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.