Tạo tên mới cho tập tin di chuyển để ngăn chặn ghi đè?


8

Làm cách nào tôi có thể tạo tên mới cho một tệp nếu có tệp hiện có cùng tên đó? Trong môi trường Máy tính để bàn, một tên mới được tạo ra để tôi thêm một số vào cuối tên tệp, nhưng làm thế nào để thực hiện được điều này từ dòng lệnh?

Tôi đang sử dụng hệ điều hành Android với Busybox.


1
Bạn có thể mở rộng Q của bạn để chỉ định khả năng bạn muốn tạo các tệp này đối với Android không? Java? Bạn có dụng cụ gì, busybox? Hay chỉ là vani android?
slm

@user slm Tôi sẽ sử dụng nó để sao lưu các tệp có trong thư mục tải xuống trên máy tính bảng của mình, chương trình sắp xếp các tệp dựa trên phần mở rộng vào các thư mục tương ứng, tôi đã viết một tập lệnh python thực hiện điều này, nhưng chương trình chậm và cũng ghi đè lên một tập tin nếu nó có cùng tên. Tôi đang trong quá trình viết lại chương trình thành bash, tạo ra một tên mới là phần mà tôi đang vật lộn.
kyle k

Cảm ơn bạn đã trả lời! Bạn có quyền truy cập sau đó đến một phiên bản mktemp?
slm

@user slm Tôi đã cài đặt busybox và nó được bao gồm, nhưng nếu tôi thực hiện một cuộc gọi hệ thống từ một chương trình mktempsẽ không hoạt động.
kyle k

Không hoạt động với một số loại lỗi? Ngoài ra, bạn đang thực hiện cuộc gọi hệ thống này từ đâu? Con trăn?
slm

Câu trả lời:


5

Giả sử bạn có vỏ POSIX, bạn có thể làm điều này:

mv() {
        eval "DEST=\${$#}" #The destination is the last positional parameter
        if [ -e "$DEST" ] && ! [ -d "$DEST" ];then
                PREFIX=${DEST%.*}
                COUNT=1
                EXT=${DEST##*.}
                args= i=1
                while [ $i -lt $# ]; do args="$args \"\${$i}\"" i=$((i+1)); done
                DEST="$NAME-"$(printf "%03d" $COUNT)".$EXT"
                while [ -e "$DEST" ];do
                    COUNT=$((COUNT+1))
                    DEST="$NAME-"$(printf "%03d" $COUNT)".$EXT"
                done
                eval "command mv $args \"\$DEST\""
        else
                command mv "$@"
        fi
}

Làm thế nào để sử dụng này

Đây là một chức năng vì vậy hãy lưu nó trong của bạn ~/.bashrcvà gọi nó như bình thường mv.

Cái này làm gì

  • Lưu trữ đường dẫn đến mvtệp thực thi ban đầu trong MVbiến
  • Nhận được đối số cuối cùng mà nó được gọi với biến DEST
  • Nếu DESTtồn tại và không phải là một thư mục, hàm này giả định rằng việc đổi tên của bạn đang cố gắng ghi đè lên một tệp
  • Sau đó, nó trích xuất tiền tố của tên cuối cùng (bất cứ điều gì trước trận chung kết ., đánh dấu phần mở rộng), phần mở rộng (bất cứ điều gì sau trận chung kết .), số đếm (nếu có; bất cứ điều gì trong tiền tố sau trận chung kết -).
  • Số lượng trích xuất được đặt thành 0 nếu không tìm thấy số đếm khác, nó được đặt thành số đếm được tìm thấy trong bước trước.
  • Số lượng hiện tại được tăng lên
  • Sau đó, hàm sẽ tự gọi với tất cả các đối số gốc (khóa + tên tệp) trừ đi đối số cuối cùng và thêm tên tệp mới thay vì đối số cuối cùng trong cuộc gọi ban đầu. Tên mới là tên cũ nhưng có bộ đếm 3 chữ số (không nhồi) được thêm vào trước phần mở rộng.
  • Hàm này là đệ quy vì nếu bạn nói mv a.txt b.txtnó sẽ thử trước mv a.txt b-001.txt. Cuộc mvgọi tiếp theo này cũng phải là chính chức năng bởi vì nếu b-001.txtcũng tồn tại, chúng tôi muốn tiếp tục tăng bộ đếm cho đến khi chúng tôi tìm thấy một tên tệp mới không tồn tại.
  • Nếu đối số cuối cùng không tồn tại hoặc là một thư mục, thì mvtệp thực thi ban đầu được gọi với các đối số ban đầu của bạn.

Hãy cẩn thận

  • Số lần bạn có thể liên tục cố gắng ghi đè một tệp hiện có tùy thuộc vào độ dài của bộ đếm (999 lần trong trường hợp này). Bạn có thể chọn một số chữ số bao gồm giới hạn inode trên hệ thống tệp của bạn để đảm bảo rằng nó sẽ hoạt động miễn là bạn có thể tạo tệp.
  • Nếu bạn cố gắng ghi lại một tập tin có tên tương tự foo-001.txt, nó sẽ được chuyển đến foo-001-001.txt.

Ghi chú

  • Để thay đổi mô hình đặt tên, thay đổi 3trong printftuyên bố bất cứ điều gì bạn muốn.
  • Mã này đã được thử nghiệm
  • Điều này rất đơn giản và tôi chắc chắn sẽ có những trường hợp cạnh mà nó thất bại thảm hại. Tôi rất vui khi thử và sửa chúng cho bạn nếu bạn tìm thấy bất kỳ. Trong khi đó, đừng thử điều này trên máy sản xuất.

cùng tâm trí ở đây: P
Rahul Patil

@RahulPatil Ngoại trừ tôi đang cố gắng sao chép hành vi GUI.
Joseph R.

thật tuyệt, tôi chưa sử dụng GUI.
Rahul Patil

nó ghi đè lên tệp đích nếu nó thoát, tôi đã kiểm tra paste.ubfox.com/6071897
Rahul Patil

@RahulPatil Không chắc chắn những gì bạn đang nói: trong ví dụ của bạn, nó đã xác định đó /tmplà một thư mục tồn tại và được gọi là /bin/mv file1 /tmpTôi không thấy vấn đề ở đâu.
Joseph R.

3

Tôi thường sử dụng công cụ mktempđể tạo các tập tin tạm thời đáng tin cậy. Nó mặc định để tạo tập tin, nhưng cũng có thể tạo thư mục thông qua -dchuyển đổi của nó .

Thí dụ

Đây là cách bạn có thể tạo một số tên tạm thời cho các tệp trong thư mục hiện tại của bạn.

$ mktemp somefile.XXXXX
somefile.kiDad

$ mktemp somefile.XXXX
somefile.MrSW

$ mktemp someotherfile.XXXXXXXXXXX
someotherfile.Um4aXKrt3lv

Điều này sẽ tạo ra các tập tin cho bạn.

Người giới thiệu


2
Không có mktemptrên Android, nhưng +1 từ tôi vì dù sao đây cũng là một câu trả lời hay cho một câu hỏi hay, U & L khôn ngoan.
goldilocks

@goldilocks - cảm ơn bạn vì những lời tốt đẹp của bạn. Nó luôn luôn tốt đẹp!
slm

@goldilocks - Bạn có biết offhand nếu busybox được bao gồm? Có một triển khai mktemp trong đó, tôi không biết nhiều về Android. code.google.com/p/abb/source/browse/mktemp.c?name=upstream/ trên
slm

1
Có vẻ như busybox trên Android yêu cầu thiết bị phải được root (jailbreak). Shell nguyên gốc /system/bin/shvà dường như shtương thích - các cấu trúc như if [ -w $file ]công việc mvrenamecó sẵn - vì vậy một tập lệnh để làm điều này chỉ với các phần dựng sẵn nên hoạt động ở đó.
goldilocks

@goldilocks - cảm ơn bạn đã kiểm tra. Bạn đang tìm kiếm điều gì? Tôi muốn bị ướt chân với Android nhưng không muốn có điện thoại / thiết bị.
slm

2

Đây là một thay thế cho kịch bản của Joseph R không có sự cảnh báo nào! Nó sẽ nối một hậu tố số vào một tên đường dẫn (đường dẫn có thể là một thư mục hoặc một tệp), tăng giá trị hậu tố cho đến khi tìm thấy một hậu tố chưa tồn tại. Các tiện ích khác như logrotatesử dụng một mẫu tương tự, nhưng xoay tất cả các bản sao hiện có để cái mới luôn có '0' cho hậu tố. Vì đây không phải là một vòng quay theo nghĩa đó, tôi sẽ gọi nó dotmv. Chỉ cần nhớ rằng đó file.0sẽ là bản sao cũ nhất .

Ví dụ:

dotmv somefile.txt

Đổi tên somefile.txt somefile.txt.0, trừ khi cái sau tồn tại, trong trường hợp đó sẽ là somefile.txt.1, và như vậy. Bạn có thể liệt kê nhiều hơn một tệp ( dotmv this that "the other thing"v.v.), tất cả chúng sẽ được di chuyển theo dấu chấm.

Tôi tin rằng đây là tuân thủ POSIX - nó chạy với set -o posixbash (nhưng đó là một thử nghiệm đáng ngờ). Tôi cũng đã thử nghiệm với trình bao Android (thạch đậu 4.2.1) và nó hoạt động ở đó. Tuy nhiên, trên Android, bạn sẽ cần thay đổi shebang như được chỉ định hoặc chạy nó sh dotmv- dù sao bạn cũng sẽ trừ khi bạn có một thiết bị đã root, bởi vì không có cách nào để tạo một tập lệnh thực thi theo cách khác. Thay đổi shebang sẽ cho phép bạn sử dụng exec dotmv.

#!/bin/sh
# On android change that to /system/bin/sh.

# Validate arguments
if [ $# -lt 1 ]; then
    echo "A list of one or more paths is required."
    exit 1
fi

# Checks if a path exists and can be moved.
checkPath () {
    if [ ! -e "$1" ]; then
        echo "'$1' does not exist."
        return 1;
    fi
    if [ ! -w "$1" ]; then
        echo "Cannot move '$1', permission denied."
        return 1;
    fi
    return 0;
}

# Finds a new path with numerical suffix.
getName () {
    suf=0;
    while [ -e "$1.$suf" ]
        do let suf+=1
    done
    Dest=$1.$suf
}

# Loop through arguments -- use quotes to allow spaces in paths.
while (($#)); do
    Src=$1
    Dest=$1
    shift
    checkPath "$Src"
    if [ $? -eq 0 ]; then
        getName "$Src"
        mv "$Src" "$Dest"
    fi
done

Hy vọng logic ở đây là rất đơn giản. Điều này có thể được thực hiện bằng python, C hoặc bất kỳ ngôn ngữ thủ tục hoàn chỉnh nào khác với tệp I / O.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.