ディレクトリ内のファイルで、日付が最も古い&(且つ)サイズが小さいものを削除するシェルを作成しようと考えています。

当初の以下のような考えをしていましたが、うまくいかないので質問しました・・・

ls -lStr(カレントディレクトリで日付が古くサイズが小さい順のつもり・・・)

上記のコマンド実行にて、
合計 100
-rwxr-xr-x 1 root root 333 2月 22 2009 java.log

と表示されるのを利用し、上から2行目のファイル名を取得するためawkして『java.log』というファイル名をprintfで表示させ変数か何かに格納し、rmコマンドで削除という流れを考えていました。

よくよく考えると
・ls -lStr は本当に日付が古くサイズが小さいものでソートされているのか
・lsコマンドで表示した『2行目』という指定でファイル名の取得できるのか


がよくわからなくなってしまいました。

上記の考え方よりこっちのほうが良い!やアドバイスがあれば非常に嬉しいです。


よろしくお願いしますm(__)m

このQ&Aに関連する最新のQ&A

A 回答 (1件)

「最も古い&(且つ)サイズが小さいもの」は、ちょっと意味が不明です。

両方の条件が成り立つとはかぎりません。
「最古だけどファイルサイズが最小ではないもの」
「最古ではないけどファイルサイズは最小のもの」
の2つのファイルがある場合、どちらが削除対象ですか?

「最小ではなくても、とにかく最古」が対象なら、ls -tr
「最古ではなくても、とにかく最小」が対象なら、ls -Sr

になるでしょう。

あと、lsのソート順オプションが決まったとして、その一覧の先頭に来ているファイルを削除する方法についてですが、
ls に-l オプションを付ける必要はないでしょう。
-lオプションなしならファイル名だけが表示されますから、それがそのまま削除対象として使えます。

あとは、head コマンドを使って

ls -tr | head -1

で、lsの結果の先頭1行だけが表示されますから、

rm `ls -tr | head -1`

とすれば、そのファイルだけが削除されます。
(これは、最古の1ファイルを削除する例になります)
    • good
    • 1
この回答へのお礼

最初の条件はディレクトリ内にある更新が古い日付順(同日同時刻ファイル複数)
でソートし、さらに同日同時刻の古い複数ファイルの中でファイルサイズが小さいもの
でソートというイメージでした。
1.最古の日付でソート
2.1.の中で更にサイズでソート
のような感じです。

ちなみにlsの件はできました!ありがとうございました!

お礼日時:2011/04/20 09:42

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q一番古い更新日付をチェックする

OS:RedHatLinuxES3.0
下記についてご存知お方がいらっしゃいましたら教えてください。

[file.log]と言うファイルがあります。
このファイルは、5MBになると、5MBに達した時の、年月日時分秒を付けたファイル名[file-YYYY_MM_DD-hh_mm_ss.log]になります。
また、このファイルは5世代管理とするので、[file.log]が一つ、残り4つは[file-YYYY_MM_DD-hh_mm_ss.log]となります。

そこで、質問ですが、この5つのファイルの中で一番古い更新日付を持つファイルのみを他のディレクトリにコピーしようと思っています。
つまり、[file-YYYY_MM_DD-hh_mm_ss.log]ファイル名の一番古い日付を持つファイルを選択したいのですが、いい方法がありましたら教えて下さい。

Aベストアンサー

ls -1 -t | head -1
で一番古いファイルをピックアップするのでできそうな気はします。
たとえば
cp `ls -1 -t *.log | head -1` OLDlogs/
みたいな感じで。

Q~以外を削除する場合(rmコマンド)

linuxのコマンドで
~以外のファイル、ディレクトリを全て削除したい時は
どのような記述をすれば良いのでしょうか?
シェルスクリプトではなくrmコマンド1つで削除したのいですが…

例: tar以外のファイル・ディレクトリを
   すべて削除したい場合など

どなたかご存知の方がいらっしゃったら
教えてください。よろしくお願い致します。

Aベストアンサー

rm コマンドのみという訳にはいきませんが基本的なコマンドを組み合わせると実現可能と思います。

「名前が tar で終わるもの以外のファイル・ディレクトリを削除する」場合だと

ls | grep -v -E 'tar$' | xargs rm -r

となります。

ファイルの一覧を取得し ( ls )
'tar'で終わるもの以外を抽出し ( grep )
その結果を rm -r の引数に指定して実行 ( xargs )

という流れです。

ファイルを削除するような操作については失敗するとダメージが大きいので、事前にテストして動作を確認すると良いとおもいます。また rm -r -i としてそれぞれのファイルについて、削除の問い合わせをするのも有効です。

Qシェルスクリプトでファイル内の数値文字列を数値として扱うには

失礼します。
シェルスクリプトでファイル内のテキスト(数値文字列)を取得して、それを使って計算するにはどうすれば良いでしょうか?

str:ファイル内のテキスト(数値文字列)

res=$(( $str + 1 ))

・エラー
")syntax error: invalid arithmetic operator (error token is "


よろしくお願いします。

Aベストアンサー

bashをご使用と判断して

res=$(( $str + 1 ))
ではなく、
res=$(( str + 1 ))
だと思います。

> exprもやってみたのですが、処理が遅くなるので使いません。
興味があって以下のシェルで検証してみました。

#!/bin/bash

str=1
i=0

echo 'Using $((str + 1))'
date '+%H:%M:%S.%N'

while [ $i -lt 10000 ]
do
str=$(( str + 1))
i=`expr $i + 1`
done

date '+%H:%M:%S.%N'

exit

$ ./test.sh
Using $((str + 1))
09:18:46.290418000
09:18:56.929345000
これをexprに書き換えたところ
$ ./test2.sh
Using expr
09:19:00.302748000
09:19:19.259990000

exprだと19秒ですが、$(( 演算 )) だと10秒程度なので、演算が多くなれば確かにexprは不利ですね。

bashをご使用と判断して

res=$(( $str + 1 ))
ではなく、
res=$(( str + 1 ))
だと思います。

> exprもやってみたのですが、処理が遅くなるので使いません。
興味があって以下のシェルで検証してみました。

#!/bin/bash

str=1
i=0

echo 'Using $((str + 1))'
date '+%H:%M:%S.%N'

while [ $i -lt 10000 ]
do
str=$(( str + 1))
i=`expr $i + 1`
done

date '+%H:%M:%S.%N'

exit

$ ./test.sh
Using $((str + 1))
09:18:46.290418000
09:18:56.929345000
これをe...続きを読む

Q起動しているサービスを確認するコマンド

初歩的な質問で恐縮ですが、ご教示いただけますと幸いです。

起動しているサービスを確認するために以下の2つのコマンドを打ってみるのですが、結果(出て来るサービス名)が違います。
このコマンドの違いについてご教示いただけますでしょうか。

(1)service --status-all
(2)chkconfig --list

Aベストアンサー

(1)service --status-all

サービスの現在のステータスを調べるコマンド

(2)chkconfig --list

OSのブート時に自動起動するサービスを調べるコマンド

違いが出るのは、
・ブート後に手動あるいは他のコマンドから起動したサービス
・ブート後に手動あるいは他のコマンドから、あるいはエラーで停止したサービス
・ブート後に実行はされるがすぐに停止して常駐しないサービス (ntpdate とか)

あるいは、(1)ではサービス名が表示されない物もあるので、どのサービスがどんなステータス出力をするのか知っておく必要もありますね。(service network statusとか)

Qファイル数を見て削除するシェルプログラム

mysql のデータベースを mysqldump で取得して
そいつを日付のファイル名をつけてバックアップを取っているのですが
このままだとひたすら数が増え続けてしまいます。

ファイル数を決めておいて、ある一定数になれば古いものから削除していくような
プログラムを書きたいのですが…

ちなみにファイルは一つのディレクトリにあり
db-20050101.tar.gz のようなフォーマットです。

よろしくお願いします。

Aベストアンサー

以下のようなスクリプトを実行してください。
-------------------------
#!/usr/bin/sh
#
loopcnt=0
zanfile=10
filelist=`ls -r db-????????.tar.gz` # 削除対象ファイルの一覧取得
for delfname in $filelist; do
if [ $loopcnt -ge $zanfile -a -f $delfname ]; then
rm -f $delfname || exit 10 # ファイル削除
#echo "$delfname was deleted!"
fi
loopcnt=`expr $loopcnt + 1`
done
#
# 正常終了
#
exit 0
-------------------------
shのパスはあなたのマシンの環境にあわせてください。
zanfile=10が残すファイルの数です。適切な数値をセットして下さい。
必ず削除対象ファイルが存在するディレクトリで実行して下さい。
実行してないので自信なし。

以下のようなスクリプトを実行してください。
-------------------------
#!/usr/bin/sh
#
loopcnt=0
zanfile=10
filelist=`ls -r db-????????.tar.gz` # 削除対象ファイルの一覧取得
for delfname in $filelist; do
if [ $loopcnt -ge $zanfile -a -f $delfname ]; then
rm -f $delfname || exit 10 # ファイル削除
#echo "$delfname was deleted!"
fi
loopcnt=`expr $loopcnt + 1`
done
#
# 正常終了
#
exit ...続きを読む

Qfindでフォルダだけを検索

find / -name "apache*"
これを、フォルダだけヒットするような文にするとどうなりますか?

Aベストアンサー

がると申します。

find / -name "apache*" -type d
でいかがでしょうか?

Qシェルスクリプトでファイル削除したい

シェルスクリプト初心者です
今回、Linuxサーバ側にある複数のファイルを削除する
必要が出てきました
このため、シェルスクリプトを書いて複数(2000程度)
のファイルを削除しようとして試験をしています
試験のLinuxサーバ側の/root の中にfile1,file2・・・
等々を置いています
そこに次のようなスクリプトを記載して
ファイルが置かれている場所と同じ/rootに置いて実行させるのですが

************** スクリプト ********
#!/bin/sh
echo "start"
#
#
rm F1010002.JPG
rm F1010003.JPG
rm F1010004.JPG
echo "end"

******************************



下記のようなエラーが出ます
******************************************
start
rm: cannot lstat `F1010002.JPG\r': そのようなファイルやディレクトリはありません
rm: cannot lstat `F1010003.JPG\r': そのようなファイルやディレクトリはありません
rm: cannot lstat `F1010004.JPG\r': そのようなファイルやディレクトリはありません
end
******************************************

サーバ側にSSHで入って、
# rm F1010002.JPG
とひとつひとつ打鍵していくとファイルは削除されます

スクリプトの間違い等あるのでしょうか
教えていただければ幸いです

なお、ファイル数2000件程度のスクリプトを記載する方法は
別のソフトを利用して作成できるので・・・その件はいいのですが・・・

シェルスクリプト初心者です
今回、Linuxサーバ側にある複数のファイルを削除する
必要が出てきました
このため、シェルスクリプトを書いて複数(2000程度)
のファイルを削除しようとして試験をしています
試験のLinuxサーバ側の/root の中にfile1,file2・・・
等々を置いています
そこに次のようなスクリプトを記載して
ファイルが置かれている場所と同じ/rootに置いて実行させるのですが

************** スクリプト ********
#!/bin/sh
echo "start"
#
#
rm F1010002.JPG
rm F1010003.JPG
rm F1010004.JPG
e...続きを読む

Aベストアンサー

`F1010002.JPG\r' ってファイル名の後ろに CR コードが付いていることになってますよ。
シェルスクリプトはWindowsのPCで作成してからFTPでアップロードしてませんか?
ファイルの改行コードを CR+LF から LF に変えてアップロードし直してみてください。

QLinuxでディレクトリ内の最新ファイルとファイル数を取得したいです。

ディレクトリ内にファイルが多すぎて
lsしても画面が流れてしまい困っています。

・ディレクトリのファイル数を取得したい
・ディレクトリ内の最新ファイルの日付を取得したい
のですがどうしたら良いでしょうか?

Aベストアンサー

> lsしても画面が流れてしまい困っています。
ls -ltr | more /// スペースキーで画面スクロール。
ls -ltr | tee a.txt /// a.txt にファイル名が出力されます。(リダイレクト">"よりはいいですよ。)

>・ディレクトリのファイル数を取得したい
ls -ltr | wc -l

>・ディレクトリ内の最新ファイルの日付を取得したい
ls -ltr | tail -1

Qunix の exit 1, exit 0について

unixの超初心者です。
viで作るプログラムで、if 構文の中に、exit 0 とexit 1がありますが、exit 0は、正常終了。
exit 1は、異常終了と言葉では理解してますが、よくわかりません。
(1)じぶんの理解では、exit 0がif文がとりあえず終わったと、
そして、exit 1は、後にも続くかも?みたいに理解してるんですが、elseの後なので(elseがあっても入ってない時がある)。
どうでしょうか?
(2)それと これは fiの前に入れるものなんでしょうか?
最後のexit 0は fiの後に入れてるようですが?間違い?
(3)if,else,fi. if,else,fi. if,else,fiと続く場合exit 1 を入れてないif 文もありますが、どうちがうんでしょう?
(4)exit だけの場合との違いは、何なんでしょうか?
すごく混乱してます、よろしくお教えください。

Aベストアンサー

exit にあたると、その時点で処理は終了されます。
なのでIF文の分岐でExitがあれば、そこで終了。
その下のロジックは処理されません。
Exit 0 と後ろにつける数字は終了ステータスを示します。

通常は0 を正常として、1を警告、2をエラーなどにします。
これを実行元に返し、プログラムが正常に終了したかどうかの判断元にします。
例えば、2が返された場合は、システム管理者にメールを送付するなどのアラートなんかにも使われます。

Qlinuxのシェルでファイル名に先月以前の日付があるのを削除したい

linuxのシェルでファイル名に先月以前の日付があるのを削除したい

bashでcshellでも良いのですが、
/pgsql/data/pg_log/
の下にたまったlog
postgresql-2010-04-01-*.log
postgresql-2010-03-31-*.log
postgresql-2010-03-30-*.log
などのうち、
先月以前の日付があるのを削除するスクリプトを作りたいのですが、上手くいきません。

ls postgresql*.logから全件数回して、if文で比較しようとしましたが、判定がうまくいきません。


何がネックになっているかと言いますと、
文字列「postgresql-2010-04-01-*.log」
文字列「postgresql-2010-04」をif文で比較すると、=の判定はできますが、
>や<で判定すると、全てthenになってしまいます。
文字の大小比較はできないようですね?


また、
「postgresql-2010-04-01-*.log」
から、12文字目から7文字抜き出したいのですが、
substrのような事も出来るのかどうなのか分かりません。

bashでこういう事をするのはあまり向いていないのでしょうか?
cshellとどちらが向いているでしょうか?
あるいはパールなんかを使った方が良いのでしょうか?

当面のやりたい事をクリアする方法、および、ツールの選定についてご教授下さい。

以上、よろしくお願いします。

linuxのシェルでファイル名に先月以前の日付があるのを削除したい

bashでcshellでも良いのですが、
/pgsql/data/pg_log/
の下にたまったlog
postgresql-2010-04-01-*.log
postgresql-2010-03-31-*.log
postgresql-2010-03-30-*.log
などのうち、
先月以前の日付があるのを削除するスクリプトを作りたいのですが、上手くいきません。

ls postgresql*.logから全件数回して、if文で比較しようとしましたが、判定がうまくいきません。


何がネックになっているかと言いますと、
文字列「postgresql-2010-04-01-*.lo...続きを読む

Aベストアンサー

ファイル名でなく、タイムスタンプが30日以前で削除するなら、#1の方が書いたようにfindを使うのが良いです。

find /pgsql/data/pg_log/ -name '*.log' -mtime +30 | xargs -r rm

> < の判定が失敗したのは、

if [ $file < postgresql-2010-04 ] のように書いたのではありませんか? < や > はそのまま書くとリダイレクトの記号なので、if [ $file '<' postgresql-2010-04 ] のように書かないといけません。

>12文字目から7文字抜き出したいのですが、

${file:11:7} のように書きます。先頭を0と数えるので12文字目は11になります。

>bashでこういう事をするのはあまり向いていないのでしょうか?cshellとどちらが向いているでしょうか?あるいはパールなんかを使った方が良いのでしょうか?

cshよりbashのほうが高機能です。この程度であれば、シェルで十分です。

YYYYMM=`date +%Y-%m`
cd /pgsql/data/pg_log/
for file in postgresql-*.log
do if [ $file '<' postgresql-$YYYYMM ];then rm $file;fi
done

ファイル名でなく、タイムスタンプが30日以前で削除するなら、#1の方が書いたようにfindを使うのが良いです。

find /pgsql/data/pg_log/ -name '*.log' -mtime +30 | xargs -r rm

> < の判定が失敗したのは、

if [ $file < postgresql-2010-04 ] のように書いたのではありませんか? < や > はそのまま書くとリダイレクトの記号なので、if [ $file '<' postgresql-2010-04 ] のように書かないといけません。

>12文字目から7文字抜き出したいのですが、

${file:11:7} のように書きます。先頭を0と数える...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング