কীভাবে আপনি পরীক্ষা করতে পারেন যে কোনও ফাইল অজস্রের মধ্যে রয়েছে? [-d 'ফাইলের নাম'] ব্যর্থ


10

আমি ব্যবহারকারীর একটি তালিকা তৈরি করার চেষ্টা করছি যাঁর একটি হোম ডিরেক্টরি সেট রয়েছে যা বিদ্যমান নেই। দেখে মনে হচ্ছে আমার এটি করা খুব ভাল করে করা উচিত, তবে আমার সিনট্যাক্সে কিছু ভুল।

এটি আমাকে "অবৈধ সিনট্যাক্স" বলতে থাকে]। আমি কি ভুল করছি?

awk -F: '{ if(![ -d "$6"]){ print $1 " " $3 " " $7}}' /etc/passwd

আমি সম্ভবত যে চূড়ান্ত কোডটি ব্যবহার করতে যাচ্ছি তা হ'ল:

awk -F: '{if(system( "[ -d " $6 " ]") == 1 && $7 != "/sbin/nologin" ) {print "The directory " $6 " does not exist for user " $1 }}' /etc/passwd

এবং আমি এখানে একটি সম্পর্কিত প্রশ্ন আছে

উত্তর:


14

আপনি ব্যবহার করতে পারেন

system (কমান্ড) 
    অপারেটিং-সিস্টেম কমান্ড কমান্ড কার্যকর করুন এবং তারপরে
    awk প্রোগ্রামে ফিরে আসুন। কমান্ডের প্রস্থান স্থিতি ফিরে আসুন। 

উদাহরণ:

awk -F: '{if(system("[ ! -d " $6 " ]") == 0) {print $1 " " $3 " " $7}}' /etc/passwd

আমি কোনও কারণে এটি কাজ করতে পারি না, তাই আমাকে এই কাজটি করতে হয়েছিল: awk '{if (system ("stat" $ 0 "> / dev / null 2> / dev / null") == 1) মুদ্রণ করুন $ 0 } '
আলেকজান্ডার কেজেল

1
@ আলেকজান্ডারজেল - একটি ডিরেক্টরি অস্তিত্বের জন্য এই পরীক্ষাগুলি - আপনি যদি নিয়মিত ফাইলের উপস্থিতি আছে কিনা তা দেখার চেষ্টা করছেন তবে উপরের কোডটি ব্যর্থ হবে তা সুস্পষ্ট ...
don_crissti 25:17

3
এটি অত্যন্ত বিপজ্জনক! ইনপুট উপর নির্ভর করে নির্বিচার কমান্ড কার্যকর করা যেতে পারে । উদাহরণস্বরূপ নিম্নলিখিত মৃত্যুদণ্ড কার্যকর /bin/ls: echo ';ls;' | awk '{ print system("[ ! -d " $1 " ]") }'
টিনো 22

6

আমি মনে করি না যে [ -d ]এটি একটি awkজিনিস, এটি একটি শেল জিনিস। পরিবর্তে আমি কেবল এটি এইভাবে করব:

awk -F: '{ print $1,$3,$7}' /etc/passwd | 
    while read name uid shell; do 
        [ -d "/home/$name" ] || echo "$name $uid $shell"; 
    done

অবশ্যই, @ জ্যানিসের দ্বারা ঠিক সঠিকভাবে নির্দেশিতভাবে, আপনি শেলটিতে পুরো কাজটি করতে পারেন:

while IFS=: read  name x uid x x x shell rest; do
     [ -d "/home/$name" ] || echo "$name $uid $shell" 
done < /etc/passwd

ঠিক আছে, আমি মনে করি আমি আসলে ir 6 কে দির হিসাবে পাস করতে চাই, এবং -ড $ দির, তবে এটি অনেক সাহায্য করে। এখনই আমাকে খুঁজে বের করতে হবে যদি কোনও ফলাফল না পাওয়া যায় তবে কীভাবে "কোনও ফলাফল" প্রতিধ্বনি করা যায়। ধন্যবাদ!
ডগ

2
নোট করুন যে awkআসলে প্রয়োজন হয় না; যেহেতু আপনি শেলটি লুপ করেন তবে আপনি কেবল এটি করতে পারেন while IFS=: read -r name x uid x x x shell rest ; do ... ; done </etc/passwd
জানিস

@ ডগ ঠিক করুন awk -F: '{print $6}' /etc/passwd | while read dir; do [ -d "$dir" ] || echo "no results for $dir"; done
টেরডন

@ জানিস সত্যই, ভাল পয়েন্ট, উত্তর সম্পাদিত।
টেরডন

@ ইটারডন নোট হিসাবে, [ -d "$6"]আসলে বাশ বাক্য সিনট্যাক্স, অদ্ভুত নয়। [স্বাভাবিক সিনট্যাক্স মত দেখায়, কিন্তু (ব্যাশ / লিনাক্স এর ভাল weirdnesses এক) এটি আসলে জন্য একটি প্রতিশব্দ এর testএক্সিকিউটেবল প্রোগ্রাম (হয়তো বা একটি ব্যাশ বিল্ট-ইন এটা সংস্করণ, এবং, মাত্র weirder হতে, ব্যাশ একটি মানানসই প্রয়োজন ]যে ফেলে না আপনাকে ভ্রান্ত করা ছাড়া পুরো বিষয়টি সত্যই একটি সিনট্যাক্স, কোনও প্রোগ্রাম নয়) এর বাইরে আমি আর কিছু জানি না। যাই হোক না কেন, এটি বিশ্রী কিছু সম্পর্কে জানে না। এজন্য আপনার system()বোঝার প্রসঙ্গে যেখানে এটি বোঝা যায় তার প্রসঙ্গে উল্লেখ করে এটি অ্যাক্সেস করার জন্য আপনার ফাংশনটি প্রয়োজন
জো

6

আপনি গেটলাইন ব্যবহার করতে পারেন :

awk 'BEGIN {print getline < "file" < 0 ? "not exists" : "exists"}'

1
এটি নিরাপদে awkতবে দুর্ভাগ্যক্রমে ডিরেক্টরিগুলির জন্য কাজ করে না।
টিনো 22

5

আপনি যদি সত্যিই ব্যবহার করছেন gawk(যদিও আপনি ব্যবহার করছেন nawk, অথবা mawk, এটি ক্ষেত্রে প্রযোজ্য না হয়), আপনি v4.0 থেকে উপলব্ধ লোডযোগ্য এক্সটেনশানগুলির একটি ব্যবহার করে স্থানীয়ভাবে এটি করতে পারেন । আমি ব্যবহার করছি (v4.0 এক্সটেনশনগুলি লোড করার জন্য সিনট্যাক্সে একটি ভিন্নতা ছিল)।gawk-4.1.x

filefuncsএক্সটেনশন লোড করা একটি stat()ফাংশন যুক্ত করে (অন্যদের মধ্যে) :

@load "filefuncs"
BEGIN {FS=":"}
(NF==7) {
   printf("user: %s %i %i\n",$1,$3,$4)
   rc=stat($6,fstat)
   err=ERRNO  # ERRNO is a string, not an int!
   if (rc<0) { 
       printf(" error: %s rc=%i %s\n",$6,rc,err)
   } else {
      if (fstat["type"]!="directory") 
        printf("  ENOTDIR: %s %s\n",$6,fstat["type"])
      if (fstat["uid"]!=$3) 
        printf("  uid mismatch: %s %i!=%i\n",$6,fstat["uid"],$3)
      if (fstat["gid"]!=$4) 
        printf("  gid mismatch: %s %i!=%i\n",$6,fstat["gid"],$4)
   }
}

filefuncs(3am)এই এক্সটেনশনের বিশদটির জন্য ম্যান পৃষ্ঠাটি দেখুন ।

এর মতো কিছু দিয়ে চালান:

gawk -f testhome.awk <(getent passwd)    # bash/zsh and glibc
gawk -f testhome.awk /etc/passwd

আপনি নিশ্চিত করতে পারেন যে আপনার gawkবাইনারি এর সাথে এক্সটেনশানগুলিকে সমর্থন করে:

BEGIN { 
  if (!("api_major" in PROCINFO)) 
    printf("No extension API.\n")
  else
    printf("Extension API v%s.%s.\n",PROCINFO["api_major"],PROCINFO["api_minor"])
}

পাশাপাশি: ফাইলটি gawkপড়ার জন্য একটি ছোট লাইব্রেরি ফাংশন নিয়ে আসে passwd, আপনি এটির মতো অনুরোধ করতে পারেন:

gawk -i passwd.awk -- 'BEGIN { while(uu=getpwent()) {print uu;} endpwent(); }'

আমি getentলিনাক্স / গ্লিবসি সিস্টেমগুলিতে ব্যবহার করতে পছন্দ করি কারণ এটি এনএসউইচ সমর্থন করে।


1
মজাদার. আমি gawkv4 অফার সম্পর্কে সচেতন ছিল না । ধন্যবাদ!
টিনো 23

3

এটি প্রায় অদ্ভুত ...

perl -F: -ane 'if(!-d $F[5]){ print "$F[0] $F[2] $F[6]" }' /etc/passwd

0

এখানে একটি সমাধান যা

  • ব্যবহার gawkএবং/bin/sh
  • ডিরেক্টরি কিছু বাহ্যিক কমান্ড দিয়ে পরীক্ষা করে
  • তবে এটি নিরাপদ ও সুরক্ষিত উপায়

কোড:

gawk -F: '{
    cmd="IFS=\"\" read -r dir; [ -d \"$dir\" ]; echo $?";
    print $6 |& cmd;
    cmd |& getline x;
    close(cmd);
    if (x) print x " " $1 " " $3 " " $7
}' /etc/passwd

ব্যাখ্যা:

  • IFS="" read -r dir; [ -d "$dir" ]; echo $?হ'ল একটি শেল কোড যা ডিরেক্টরি থেকে স্টিডিন এবং আউটপুটগুলির 0কোনও পাঠ পড়ে যদি তা ডিরেক্টরি হয়, অন্যথায়1
  • print $6 |& cmdকমান্ড ফাইল নাম পাইপ। |&এটি একটি GNU-awk এক্সটেনশন।
  • cmd |& getline x কমান্ডের আউটপুট GNU-awk পড়বে
  • close(cmd) কমান্ড শেষ করে, সুতরাং পরবর্তী লাইনটি আবার একটি কার্যকর করতে পারে
  • if (x)executes printশুধুমাত্র যদি xনয় 0(বিদ্যমান নয় তাই ডিরেক্টরির করে)

আমি এটি এইভাবে করার পরামর্শ দিচ্ছি না, যদিও এটি খুব ধীর এবং আনাড়ি। তবে এই রেসিপিটি নিরাপদ , যেমন অনিয়মিত ইনপুট ক্ষতি করতে পারে না। (এটি /etc/passwdক্ষতিকারক ডেটা ধারণ করার সম্ভাবনা কম তবে সম্ভবত কেউ এটি অবিশ্বাস্য উত্স থেকে ডেটা সহ ব্যবহার করতে চায়)।

আপনি যদি ব্যবহার করতে না পারেন gawkতবে এটি দুর্ভাগ্যজনক। সেক্ষেত্রে আপনার নেই |&। সাধারণ awkকেবল নিম্নলিখিত তিনটির মধ্যে একটি করতে পারে:

  • print "data" | cmd; close(cmd): পাইপ তথ্য একটি কমান্ড মধ্যে
  • getline data < cmd; close(cmd): একটি আদেশ থেকে তথ্য পড়ুন
  • ret = system(cmd): কমান্ডের রিটার্ন কোড পান

"সাধারণ" awkসহজেই কোনও স্ক্রিপ্টে ডেটা পাইপ করতে পারে না এবং একই সাথে আবার কিছু থেকে বের করে আনতে পারে (কমপক্ষে আমি এর জন্য কোনও উপায় পাইনি), সুতরাং আপনার কিছু মধ্যবর্তী ফাইল (টেম্পাইল) প্রয়োজন যা আরও বেশি আনাড়ি।

মজার আকর্ষণীয় পর্যবেক্ষণটি হ'ল, শেল দিয়ে এই জাতীয় কাজটি খুব সহজেই করা যেতে পারে:

dump_problems()
{
have=0;
while IFS=: read -r user pw id grp gcos dir shl;
do
  [ -d "$dir" ] && continue;
  echo "$user $id $shl";
  have=1;
done </etc/passwd;
return $have;
}

dump_problems && echo ALL OK >&2 || echo "Problems were found" >&2

আপনার দরকার নেই bash, প্রতিটি সাধারণ বোর্ন শেল উপরের কোডটি কার্যকর করতে পারে।

নোট করুন যে উপরের শেল কোডটি সত্যিকারের প্রয়োজনের তুলনায় কিছুটা বেশি বিস্তৃত, তবে কীভাবে এটি সত্যিকার অর্থে কাজ করা যায় (শেল কীভাবে কাজ করে এমন লোকেরা পুরোপুরি অভিজ্ঞ নয়) তার জন্য এটি একটি পয়েন্টার হবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.