নিঃশব্দে "এমভি" ব্যর্থ করার কোনও উপায় আছে কি?


61

মত একটি কমান্ড mv foo* ~/bar/যদি আপনার সাথে মেলে এমন ফাইল দ্বারা stderr এই বার্তাটি উত্পাদন করে foo*

mv: cannot stat `foo*': No such file or directory

তবে, স্ক্রিপ্টে আমি সেই ক্ষেত্রে কাজ করছি সম্পূর্ণরূপে ভাল হবে, এবং আমি আমাদের লগগুলি থেকে এই বার্তাটি বাদ দিতে চাই।

mvকিছু সরানো না সত্ত্বেও চুপ থাকার জন্য বলার মতো কোনও সুন্দর উপায় আছে ?


13
mv foo* ~/bar/ 2> /dev/null?
টমাস নাইম্যান

1
হ্যাঁ ভালো. আমি অনুমান করি যে আমার মনে কিছু "ভাল" ছিল, যেমন কিছু স্যুইচ করার জন্য mv। :) তবে তা অবশ্যই করবে।
জোনিক

3
আমি দেখেছি কিছু mvবাস্তবায়ন -qএগুলিকে নিঃশব্দ করার একটি বিকল্পকে সমর্থন করে তবে এটি পসিক্স স্পেসিফিকেশনের অংশ নয় mvmvগনুহ coreutils মধ্যে, উদাহরণস্বরূপ, নেই না যেমন একটি অপশন আছে।
টমাস নাইম্যান

ঠিক আছে, আমি মনে করি না সমস্যাটি কীভাবে "এমভি" কে চুপ করে থাকে তবে কীভাবে এটি আরও সঠিকভাবে করা যায়। কোনও ফাইল / ডির foo * আছে কিনা তা পরীক্ষা করা হচ্ছে এবং ব্যবহারকারীর লেখার অনুমতি রয়েছে, শেষ পর্যন্ত সম্ভবত "এমভি" চালান, সম্ভবত?
Shuu Shắc

উত্তর:


46

আপনি এটি খুঁজছেন?

$ mv  file dir/
mv: cannot stat file’: No such file or directory
$ mv  file dir/ 2>/dev/null
# <---- Silent ----->

20
দ্রষ্টব্য, এখনও ফেরতের মান! = 0, সুতরাং যে কোনও set -e(যা প্রতিটি শেল স্ক্রিপ্টে ব্যবহার করা উচিত ) ব্যর্থ হবে। আপনি || trueএকক কমান্ডের জন্য চেক নিষ্ক্রিয় করতে একটি যুক্ত করতে পারেন ।

10
@reto set -eপ্রতিটি শেল স্ক্রিপ্টে ব্যবহার করা উচিত নয়, অনেক ক্ষেত্রে এটি ত্রুটি পরিচালনকে আরও বেশি জটিল করে তোলে।
ক্রিস ডাউন

1
@ ক্রিসডাউন আমি আপনার বক্তব্যটি দেখতে পাচ্ছি। এটি দুটি দুষ্টতার মধ্যে সাধারণত একটি পছন্দ হয়। তবে যদি সন্দেহ হয় তবে আমি সফল ব্যর্থতার চেয়ে ব্যর্থ সফল রানটিকেই বেশি পছন্দ করি। (এটি কোনও গ্রাহক / ব্যবহারকারীর কাছে দৃশ্যমান না হওয়া অবধি লক্ষ্য করা যায় না)। শেল স্ক্রিপ্টগুলি শুরুর জন্য একটি বড় খনি ক্ষেত্র, কোনও ত্রুটি মিস করা এত সহজ এবং আপনার স্ক্রিপ্টটি হাইওয়াইরে যায়!
reto

14

প্রকৃতপক্ষে, আমি ভাবি না যে নিঃশব্দ mvকরা একটি ভাল পদ্ধতির (মনে রাখবেন এটি আপনাকে আগ্রহী অন্যান্য বিষয়গুলির সম্পর্কেও জানাতে পারে ... যেমন অনুপস্থিত ~/bar)। আপনার গ্লোব এক্সপ্রেশন ফলাফল প্রত্যাবর্তন না করে আপনি কেবল এটিকে নিঃশব্দ করতে চান। বাস্তবে এটি একেবারেই চালিত করবেন না।

[ -n "$(shopt -s nullglob; echo foo*)" ] && mv foo* ~/bar/

খুব আবেদনময়ী দেখাচ্ছে না এবং কেবল এতে কাজ করে bash

অথবা

[ 'foo*' = "$(echo foo*)" ] || mv foo* ~/bar/

শুধুমাত্র ব্যতীত আপনি থাকেন bashসঙ্গে nullglobসেট। যদিও আপনি গ্লোব প্যাটার্নের 3x পুনরাবৃত্তির মূল্য দিতে পারেন।


দ্বিতীয় ফর্মের সাথে মাইনর ইস্যু: foo*বর্তমান ডিরেক্টরিতে এটি কেবল একমাত্র যা পৃথিবীর সাথে মেলে তখন নাম দেওয়া ফাইলটি স্থানান্তর করতে ব্যর্থ হয় foo*। এটি প্রায়শই বিশ্বব্যাপী প্রকাশের সাথে কাজ করা যেতে পারে যা নিজের সাথে আক্ষরিক, শক্ততার সাথে মেলে না। যেমন [ 'fo[o]*' = "$(echo fo[o]*)" ] || mv fo[o]* ~/bar/
ফ্রে-সান

13

find . -maxdepth 1 -name 'foo*' -type f -print0 | xargs -0r mv -t ~/bar/

- জিএনইউতে mvচমৎকার "গন্তব্য প্রথম" বিকল্প রয়েছে ( -t) এবং xargsকোনও ইনপুট ( -r) না থাকলে তার কমান্ডটি চালানো এড়িয়ে যেতে পারে । ফাইলের নামগুলিতে ফাঁকা স্থান এবং অন্যান্য "মজার" জিনিস রয়েছে এমনটি ব্যবহার করে -print0এবং -0ততক্ষণে নিশ্চিত করে তোলে যে কোনও গোলমাল হবে না।


2
মনে রাখবেন যে, -maxdepth, -print0, -0এবং -rএছাড়াও গনুহ এক্সটেনশানগুলি হল (যদিও তাদের কিছু অন্যান্য বাস্তবায়নের ইদানিং পাওয়া যায়)।
স্টাফেন চেজেলাস

1
কবিতা, আমাদের অনেক ব্যবহারকারী লিনাক্স ব্যবহার করেন না। উত্তরের কোন অংশগুলি বহনযোগ্য নয় তা উল্লেখ করার জন্য এটি এখানে স্ট্যান্ডার্ড অনুশীলন এবং খুব সহায়ক। সাইটটিকে " ইউনিক্স এবং লিনাক্স" বলা হয় এবং অনেক লোক বিএসডি বা ইউনিক্স বা এআইএক্স বা ম্যাকোস বা এমবেডেড সিস্টেমের কিছু ফর্ম ব্যবহার করে। এটি ব্যক্তিগতভাবে গ্রহণ করবেন না।
টেরডন

আমি ব্যক্তিগতভাবে কিছু নিচ্ছি না। আমার যদিও মতামত রয়েছে যে আপনি এখন যেমন দেখছেন তেমন সরিয়ে দিয়েছেন। তাই আমি পুনরাবৃত্তি করছি: আমি এই মন্তব্যগুলি "নোট ইট জিএনইউ" দেখতে বেশ অর্থহীন find এগুলি মোটেও যুক্ত করার মতো নয়, প্রথমত আমার উত্তরটির স্পষ্ট ইঙ্গিত রয়েছে যে এটি GNU সংস্করণের উপর ভিত্তি করে mv
পায়গ্রে

5

এটি উপলব্ধি করা গুরুত্বপূর্ণ যে এটি আসলে শেল যা foo*মেলানো ফাইলের নামের তালিকায় এটি প্রসারিত করে , তাই mvএটি নিজেই কিছু করতে পারে।

এখানে সমস্যাটি হ'ল যখন কোনও গ্লোব মেলে না, তখন কিছু শেল bash(এবং বেশিরভাগ বোর্নের মতো শেলস, যে বগি আচরণটি আসলে বোর্ন শেল দ্বারা s০ এর দশকের শেষের দিকে প্রবর্তিত হয়েছিল) কমান্ডটিতে প্যাটার্ন ভারব্যাটিমটি পাস করে।

তাই এখানে, যখন foo*কোন ফাইল, পরিবর্তে কমান্ড (প্রাক বোর্ন শাঁস এবং বিভিন্ন আধুনিক শাঁস মত না) গর্ভপাত এর সাথে মেলে না, শেল একটি ধারণকৃত পাসের foo*ফাইল mv, তাই মূলত জিজ্ঞাসা mvনামক ফাইল স্থানান্তর করতে foo*

এই ফাইলটির অস্তিত্ব নেই। যদি এটি হয়ে থাকে তবে এটি আসলে প্যাটার্নটির সাথে মিলেছে তাই mvকোনও ত্রুটির কথা জানায়। যদি প্যাটার্নটি foo[xy]পরিবর্তিত হয়ে mvথাকে তবে ভুলক্রমে ফাইল এবং ফাইলগুলির foo[xy]পরিবর্তে কল করা কোনও ফাইল সরিয়ে নিতে পারত ।fooxfooy

এখন, এমনকি সেই শেলগুলিতেও যে সমস্যা নেই (প্রাক-বোর্ন, সিএসএস, টিসিএস, ফিশ, জেডএস, বাশ-ও ফেলগ্লোব) আপনি এখনও ত্রুটি পেয়ে যাবেন mv foo* ~/bar, তবে এবার শেলের সাহায্যে।

যদি কোনও ফাইলের মিল নেই foo*এবং সে ক্ষেত্রে কোনও কিছুই না সরানো হয় তবে আপনি এটিকে ত্রুটি হিসাবে বিবেচনা করতে না চাইলে আপনি প্রথমে ফাইলগুলির তালিকা তৈরি করতে চান (এমনভাবে যা nullglobবিকল্পটির বিকল্পটি ব্যবহার করে কোনও ত্রুটি সৃষ্টি করে না কিছু শেল) এবং তারপরে কেবল কলটি mvতালিকাটি খালি নয়।

এটি সমস্ত ত্রুটিগুলি mv(যেমন যুক্ত করা 2> /dev/null) গোপন করার চেয়ে ভাল হবে যেন mvঅন্য কোনও কারণে ব্যর্থ হয় তবে আপনি সম্ভবত এটি কেন জানতে চান।

zsh এ

files=(foo*(N)) # where the N glob qualifier activates nullglob for that glob
(($#files == 0)) || mv -- $files ~/bar/

বা অস্থায়ী পরিবর্তনশীল ব্যবহার এড়াতে একটি বেনামি ফাংশন ব্যবহার করুন:

() { (($# == 0)) || mv -- "$@" ~/bar/; } foo*(N)

zshসেই শেলগুলির মধ্যে একটি যা বোর্ন বাগ নেই এবং কোনও গ্লোব মেলে না (এবং nullglobবিকল্পটি সক্ষম করা হয়নি) কমান্ডটি কার্যকর না করেই ত্রুটির খবর দেয় , সুতরাং এখানে আপনি zshত্রুটিটি আড়াল করে পুনরুদ্ধার করতে পারবেন stderr এর জন্য mvআপনি এখনও mvযদি ত্রুটিগুলি দেখতে পান তবে কোনও মিল না হওয়া গ্লোবগুলি সম্পর্কে ত্রুটি নয়:

(mv 2>&3 foo* ~/bar/) 3>&2 2>&-

অথবা আপনি zargsযদি এমন সমস্যাগুলি এড়াতে পারেন যা foo*বিশ্বব্যাপী খুব ম্যান ফাইলগুলিতে প্রসারিত হয় তবে সমস্যাগুলি এড়ানো যাবে।

autoload zargs # best in ~/.zshrc
zargs -r -- foo* -- mv -t ~/bar # here assuming GNU mv for its -t option

Ksh93 এ:

files=(~(N)foo*)
((${#files[#]} == 0)) || mv -- "${files[@]}" ~/bar/

ব্যাশে:

bashnullglobশুধুমাত্র একটি গ্লোব সক্ষম করার জন্য কোনও সিনট্যাক্স নেই এবং failglobবিকল্পটি বাতিল হয়ে যায় nullglobযাতে আপনার মতো জিনিসগুলির প্রয়োজন হয়:

saved=$(shopt -p nullglob failglob) || true
shopt -s nullglob
shopt -u failglob
files=(foo*)
((${#files[@]} == 0)) || mv -- "${files[@]}" ~/bar/
eval "$saved"

বা সংরক্ষণের জন্য বিকল্পগুলিকে সেট করে সেভ করার জন্য সেগুলি আগে সংরক্ষণ করতে হবে এবং পরে তাদের পুনরুদ্ধার করতে হবে।

(
  shopt -s nullglob
  shopt -u failglob
  files=(foo*)
  ((${#files[@]} == 0)) || mv -- "${files[@]}" ~/bar/
)

মধ্যে yash

(
  set -o nullglob
  files=(foo*)
  [ "${#files[@]}" -eq 0 ] || mv -- "${files[@]}" ~/bar/
)

মধ্যে fish

ফিশ শেলের মধ্যে নাল্লোগ্লোব আচরণটি setকমান্ডের জন্য ডিফল্ট , সুতরাং এটি ঠিক:

set files foo*
count $files > /dev/null; and mv -- $files ~/bar/

POSIXly

nullglobপসিক্সে কোনও বিকল্প নেই shএবং অবস্থানগত পরামিতিগুলি ছাড়া অন্য কোনও অ্যারে নেই। গ্লোব মিলছে কি না তা সনাক্ত করতে আপনি ব্যবহার করতে পারেন এমন একটি কৌশল রয়েছে:

set -- foo[*] foo*
if [ "$1$2" != 'foo[*]foo*' ]; then
  shift
  mv -- "$@" ~/bar/
fi

একটি foo[*]এবং foo*গ্লোব উভয়ই ব্যবহার করে আমরা সেই ক্ষেত্রে যেখানে কোনও মিল নেই এমন ফাইলের মধ্যে এবং যেখানে একটি ফাইল রয়েছে যেখানে ডাকা হয় তার মধ্যে পার্থক্য করতে পারি foo*(যা set -- foo*করতে পারে না)।

আরও পড়া:


3

এটি সম্ভবত সেরা নয় তবে আপনি findফোল্ডারটি খালি কিনা তা পরীক্ষা করতে কমান্ডটি ব্যবহার করতে পারেন :

find "foo*" -type f -exec mv {} ~/bar/ \;

1
এটি একটি আক্ষরিক foo*অনুসন্ধানের পথ দেবে find
কুসালানন্দ

3

আমি ধরে নিচ্ছি যে আপনি ব্যাশ ব্যবহার করছেন, কারণ এই ত্রুটিটি তুলনামূলকভাবে গ্লোবগুলি নিজের কাছে প্রসারিত করতে বাশের আচরণের উপর নির্ভর করে। (তুলনা করে, তুলনামূলকভাবে তুলনামূলক তুলনায় zsh একটি ত্রুটি উত্থাপন করে যখন তুলনাহীন গ্লোবকে প্রসারিত করার চেষ্টা করে))

সুতরাং, নিম্নলিখিত workaround সম্পর্কে কি?

ls -d foo* >/dev/null 2>&1 && mv foo* ~/bar/

এটি mvযদি ls -d foo*ব্যর্থ হয় তবে নিঃশব্দে তা অগ্রাহ্য করবে , লগিং ত্রুটি যদি ls foo*সফল হয় তবে mvব্যর্থ হয়। (সতর্কতা অবলম্বন করুন, বিদ্যমান না থাকার ls foo*কারণে অন্যান্য কারণে ব্যর্থ হতে পারে foo*, যেমন, অপর্যাপ্ত অধিকার, এফএসের সমস্যা ইত্যাদি), সুতরাং এই পরিস্থিতিতে এই সমাধানটি চুপচাপ উপেক্ষা করা হবে।)


আমি বেশিরভাগ বাশ সম্পর্কে আগ্রহী, হ্যাঁ (এবং আমি প্রশ্নটি ট্যাগ করেছিলাম bash)। অ্যাকাউন্টটি গ্রহণের জন্য +1 যা বিদ্যমান না থাকার mvকারণে অন্যান্য কারণে ব্যর্থ হতে পারে foo*
জোনিক

1
(বাস্তবে আমি সম্ভবত এটি ব্যবহার করব না কারণ এটি একধরনের ভার্বোস, এবং lsকম্যান্ডের মন্তব্যটি ভবিষ্যতের পাঠকদের পক্ষে খুব কম স্পষ্ট হবে না, কমপক্ষে কোনও মন্তব্য না করেই।)
জোনিক

ls -d foo*অন্যান্য কারণেও শূন্য-বহির্গমন প্রস্থানের সাথে ফিরে আসতে পারে যেমন একটি ln -s /nowhere foobar(অন্তত কিছু lsবাস্তবায়ন সহ) like
স্টাফেন চেজেলাস

3

আপনি উদাহরণস্বরূপ করতে পারেন

mv 1>/dev/null 2>&1 foo* ~/bar/ অথবা mv foo* ~/bar/ 1&>2

আরও তথ্যের জন্য দেখুন: http://mywiki.wooledge.org/BashFAQ/055


mv foo* ~/bar/ 1&>2কমান্ডটি নিরব করে না, স্টাডাউটে যা থাকত তা প্রেরণ করে স্ট্যাডারেও।
ক্রিস ডাউন

এবং আপনি উইন্ডোগুলি (আমার মত) অধীনে mingw ব্যবহার করছেন প্রতিস্থাপন /dev/nullসঙ্গেNUL
Rian স্যানডারসন

এই আদেশটি কীভাবে কাজ করে? অ্যাম্পারস্যান্ডগুলি কী করে? আমাদের কি করতে 1এবং 2এর অর্থ কি?
অ্যারন ফ্র্যাঙ্ক

লিনাক্স প্রক্রিয়াটি তৈরি হয়ে গেলে @ অ্যারোনফ্রঙ্ক 1 টি স্ট্যান্ডআউট এবং 2 ডিফল্টরূপে স্টডার পাইপ হয়। লিনাক্স কমান্ডের পাইপ সম্পর্কে আরও জানুন। আপনি এখানে শুরু করতে পারেন - ডিজিটালওসন / কম্যুনিটি / টিউটোরিয়ালস /
মিথুন বি

2

আপনি এর সাথে প্রতারণা করতে পারেন (বহনযোগ্যভাবে) perl:

perl -e 'system "mv foo* ~/bar/" if glob "foo*"'

ডাউনভোটিংয়ের আগে মন্তব্য করুন।
জোসেফ আর।

2

আপনি যদি পার্ল ব্যবহার করতে চলেছেন তবে আপনি পাশাপাশি যেতে পারেন:

#!/usr/bin/perl
use strict;
use warnings;
use File::Copy;

my $target = "$ENV{HOME}/bar/";

foreach my $file (<foo*>) {
    move $file, $target  or warn "Error moving $file to $target: $!\n";
}

বা এক-লাইনার হিসাবে:

perl -MFile::Copy -E 'move $_, "$ENV{HOME}/bar/" or warn "$_: $!\n" for <foo*>'

( moveকমান্ডের বিশদ জন্য, ফাইলের জন্য নথি দেখুন: অনুলিপি ।)


-1

পরিবর্তে

mv foo* ~/bar/

আপনি করতে পারেন

cp foo* ~/bar/
rm foo* 

সহজ, পাঠযোগ্য :)


6
অনুলিপি করা, তারপরে অপসারণ করা, সরল পদক্ষেপের চেয়ে বেশি সময় নেয়। কোনও ফাইল উপলব্ধ ফ্রি ডিস্ক জায়গার চেয়ে বড় হলে এটিও কাজ করবে না।
অ্যান্টন

11
ওপি এমন একটি সমাধান চায় যা নিরব থাকে। আমরাও cpনা rmচুপ করে থাকলে হয় foo*কোন অস্তিত্ব নেই।
রন rothman

-1
mv foo* ~/bar/ 2>/dev/null

উপরের কমান্ডটি সফল কিনা বা আমরা পূর্ববর্তী কমান্ডের প্রস্থান স্থিতি দ্বারা খুঁজে পেতে পারি

command: echo $?

যদি প্রতিধ্বনির আউটপুট $? 0 এর বাইরে অন্যটি অর্থ কমান্ড অসমাপ্ত

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