2009-10-19 11 views
10

Tôi có một thư mục với các file mà trông như thế này:BASH: Tìm tên tập tin được đánh số cao nhất trong một thư mục nơi tên bắt đầu bằng chữ số (ls, sed)

001_something.php 002_something_else.php 
004_xyz.php  005_do_good_to_others.php 

tôi rốt cuộc muốn tạo ra một mới, trống PHP tệp có tên bắt đầu bằng số tiếp theo trong chuỗi.

LIST=`exec ls $MY_DIR | sed 's/\([0-9]\+\).*/\1/g' | tr '\n' ' '` 

Mã trước mang lại cho tôi một chuỗi như thế này:

LIST='001 002 004 005 ' 

Tôi muốn lấy mà 005, tăng một, và sau đó sử dụng con số đó để tạo ra tên tập tin mới. Làm thế nào để tôi làm điều đó trong BASH?

+0

Đây có phải là để chạy như một phần của một ứng dụng web? Nếu máy chủ web chấp nhận nhiều yêu cầu đồng thời (hầu hết là làm), bạn sẽ bảo vệ chống lại điều kiện chủng tộc như thế nào khi các tiến trình A và B thực hiện kiểm tra đồng thời và sau đó tạo một tệp có cùng số? – telent

+0

không có điều này là một phần của một kịch bản trình bao để mô phỏng công cụ 'di chuyển' của đường ray, cho một ứng dụng php sử dụng triển khai thực hiện bước đầu đỏ của mẫu di chuyển cơ sở dữ liệu. – Jake

Trả lời

10
$ LIST=($LIST) 
$ newfile=`printf %03d-whatever $((10#${LIST[${#LIST}]}+1))` 
$ echo $newfile 
006-whatever 

Vì vậy, thật cụ thể. Dưới đây là một giải pháp bất kỳ-posix-shell-bao gồm-bash, tôi tưởng tượng điều gì đó đơn giản hơn là có thể.

$ cat /tmp/z 
f() { 
    eval echo \${$#} | sed -e 's/^0*//' 
} 
LIST='001 002 004 005 ' 
newname=`printf %03d-whatever $(($(f $LIST) + 1))` 
echo $newname 
$ sh /tmp/z 
006-whatever 
$ 
+0

không hoạt động với '008': –

+0

Đó là vì các số bắt đầu bằng "0" là * bát phân *. – paxdiablo

+0

Ok, lỗi bát phân cố định. – DigitalRoss

0

Dưới đây là một giải pháp (bạn cần bc):

#!/bin/bash 

LIST='001 002 008 005 004 002 ' 
a=0 

for f in $LIST 
do 
    t=$(echo $f + 1|bc) 
    if [ $t -ge $a ] 
    then 
     a=$t 
    fi 
done 

printf "%03d\n" $a 
+0

Bạn cũng có thể sử dụng 'dc': t = $ (echo $ f 1 + pq | dc), hoặc' expr': t = $ (expr $ f + 1), hoặc bash math: t = $ (($ f) + 1)) – mouviciel

1
$ for file in *php; do last=${file%%_*} ; done 
$ newfilename="test.php" 
$ printf "%03d_%s" $((last+1)) $newfilename 
006_test.php 

tôi rời khỏi nó để bạn làm việc tạo ra các tập tin mới

11

Bạn có cần the whole list?

Nếu không

LAST=`exec ls $MY_DIR | sed 's/\([0-9]\+\).*/\1/g' | sort -n | tail -1` 

sẽ cung cấp cho bạn chỉ là một phần 005 và

printf "%03d" `expr 1 + $LAST` 

sẽ in số tiếp theo trong chuỗi.

+0

cách khác: printf "% 03d" $ ((1 + $ LAST)) – leedm777

2

Nhanh, subshell-miễn phí và loop-free (cũng xử lý tên tập tin với không gian) *:

list=([0-9]*) 
last=${list[@]: -1} 
nextnum=00$((10#${last%%[^0-9]*} + 1)) 
nextnum=${nextnum: -3} 
touch ${nextnum}_a_new_file.php 

Với ví dụ của bạn tập tin đầu ra sẽ là:

006_a_new_file.php 
7

Sử dụng công cụ duy nhất tiêu chuẩn, sau đây sẽ cung cấp cho bạn tiền tố cho tệp mới (006):

 
ls [0-9]* | sed 's/_/ _/' | sort -rn | awk '{printf "%03d", $1 + 1; exit}' 
+1

nếu tệp 001 không tồn tại, lệnh này không in ra 001? – Stefan

+0

Điều này không hoạt động trên các thư mục chứa nhiều, nhiều tệp - đầu ra là: bash:/bin/ls: Danh sách đối số quá dài –

+0

@John: Chỉ cần thay 'ls [0-9] *' bằng 'ls | grep^[0-9] '. – Idelic

3

Điều này có vẻ đơn giản hơn.

ls [0-9]* | sort -rn | awk '{FS="_"; printf "%03d_new_file.php\n",$1+1;exit}' 
1
  1.  
    touch "newfile_$(printf "%03d" $(echo $(ls 00?_*.php|sed 's/_.*//'|sort -rn|head -1)+1|bc))" 
    

    2.

    num=$(ls 00?*.php|sed 's/.*//'|sort -rn|head -1) 
    touch $(printf "newfile_%03d" $((num+1)))

Các vấn đề liên quan