Làm cách nào tôi có thể sao chép tệp trong tập lệnh bash và đổi tên tệp trong khi sao chép và đặt tệp đó vào cùng thư mục


7

Làm cách nào để sao chép một tập tin "file.doc" và đổi tên nó trong khi sao chép vào "file_copy.doc" và đặt nó trong cùng một thư mục?

Và điều này chỉ bằng cách gọi tập lệnh và thêm tên tệp trong đối số:

bash launch_copyer file.doc

Nếu bạn không khăng khăng với Bash, tôi nghĩ cũng có những công cụ làm sẵn cho việc đó.
0xC0000022L

Có lẽ đó chỉ là tôi, nhưng tôi thấy từ ngữ thực sự khó hiểu ở đây. Tại sao mvcpkhông đủ? Chúng ta có thể có một ví dụ?
Anko

Câu trả lời:


4

Không cần bashở đây, bất kỳ shtriển khai thông dịch viên tiêu chuẩn sẽ làm:

#! /bin/sh -
ret=0
for file do
  dir=$(dirname -- "$file")
  case $dir in
    (*[!/]*) dir=$dir/ # handle / and // specially
  esac
  base=$(basename -- "$file")
  name=${base%.*}
  name=${name:-$base} # don't consider .bashrc the extension in /foo/.bashrc
  ext=${base#"$name"}
  new_file=$dir${name}_copy$ext
  cp -- "$file" "$new_file" || ret=$?
done
exit "$ret"

(giả sử tên tệp và thư mục không kết thúc bằng ký tự dòng mới).

(tất nhiên, điều đó cũng sẽ làm việc với bashbashlà một trong những thông dịch viên tiêu chuẩnsh .)

Đối với một bashgiải pháp cụ thể, bạn có thể thử:

#! /bin/bash -
ret=0
re='^((.*/)?[^/])(([^/]*)(\.))?([^/]*)/*$'
for file do
  if [[ $file =~ $re ]]; then
    if [[ ${BASH_REMATCH[5]} ]]; then
      suffix=_copy.${BASH_REMATCH[6]}
    else
      suffix=${BASH_REMATCH[6]}_copy
    fi
    cp -- "$file" "${BASH_REMATCH[1]}${BASH_REMATCH[4]}$suffix" || ret=$?
  else
    printf >&2 '%s\n' "$0: Error: refusing to copy $file"
    ret=1
 fi
done
exit "$ret"

Giống như của tôi, điều này dường như cũng thất bại nếu tệp không có phần mở rộng rải rác
roaima

1
@roaima, tốt, nó có nghĩa là để giải quyết điều đó, nhưng đã có một lỗi đánh máy. Nên làm việc bây giờ. Nó cũng địa chỉ điều thích foo.d/bar, foo/.bashrc, /foođúng mà cũng giải pháp không ...
Stéphane Chazelas

2

Vì OP đang yêu cầu một giải pháp bash. Đây là một trong đó.

#!/bin/bash

if [[ ! -f $1 && $(($# != 1)) ]]; then 
    printf '%s\n' "Provide a filename"
    exit 1
fi

inFile="$1"
fileExt="${1#*.}"
destFile="${1%.*}"

cp -- "$inFile" "${destFile}_copy.$fileExt"  # As suggested, so the files that start with a dash are not ignored.

1
Điều đó sẽ thất bại trong một số trường hợp thích với những lập luận: -foo-, foo.tar.gz, /foo/bar, foo.d/bar.doc. Tôi không chắc tại sao bạn nhấn mạnh vào đối số là một tệp thông thường hoặc liên kết tượng trưng đến tệp thông thường, đó không phải là một phần của yêu cầu. Thông báo lỗi sẽ được hiển thị trên thiết bị lỗi chuẩn.
Stéphane Chazelas

1
@ StéphaneChazelas Bạn có một điểm ở đó. Tôi nên đã sử dụng --để chỉ ra kết thúc của các tùy chọn. Vâng, .docgợi ý một tập tin. Kiểm tra đó không nhất thiết là một trong hai.
Valentin Bajrami

@ StéphaneChazelas thậm chí còn ngắn hơn. Tốt để biết.
Valentin Bajrami

1
#!/bin/bash
ss=0
for file do
    cp -fp -- "$file" "${file%.*}_copy.${file##*.}" || ss=$?
done
exit $ss

Điều này không thành công nếu filekhông có phần mở rộng dấu chấm. Nếu bạn cần điều đó để làm việc, hãy sử dụng giải pháp của Stéphane Chazelas .


Điều này sẽ không sao chép các tập tin bắt đầu với một dấu gạch ngang như -foođã đề cập.
holasz

@holasz đã sửa mà. Không có kế hoạch sửa các tập tin mở rộng dấu chấm.
roaima

0
cp /example/directory/file.doc /example/directory/file_copy.doc

cái này chỉ định tên tập tin và sẽ làm những gì bạn muốn


Đó cũng không phải là điều OP yêu cầu. Những gì nó làm chỉ là sao chép tập tin nguồn vào tập tin Dest. Có một bước ngắn hơn mặc dù. cp /path/to/dir/{file.doc,file_copy.doc} Một lần nữa, OP sẽ sử dụng tham số vị trí$1
Valentin Bajrami

@ val0x00ff, giống như cp /path/to/dir/file{,_copy}.docở đây.
Stéphane Chazelas

0

Thử cái này:

#!/bin/bash
if [ -f "$1" ];
then
  cp -v "$1" _"$1"
  rename -v 's/_(.+?)\./$1_copy\./' _"$1"
fi

Kịch bản kiểm tra nếu tệp đầu vào nhận làm đầu vào tồn tại. Trong trường hợp đó, nó tạo một bản sao tạm thời của tệp và sau đó đổi tên bản sao đó thay thế dấu chấm đầu tiên trong tên của nó bằng chuỗi_copy.

Tôi hy vọng nó là những gì bạn cần.

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.