Có cách nào dễ dàng để thay thế tất cả các liên kết tượng trưng bằng tệp mà họ liên kết đến không?
Có cách nào dễ dàng để thay thế tất cả các liên kết tượng trưng bằng tệp mà họ liên kết đến không?
Câu trả lời:
Đối với một số định nghĩa của "dễ dàng":
#!/bin/sh
set -e
for link; do
test -h "$link" || continue
dir=$(dirname "$link")
reltarget=$(readlink "$link")
case $reltarget in
/*) abstarget=$reltarget;;
*) abstarget=$dir/$reltarget;;
esac
rm -fv "$link"
cp -afv "$abstarget" "$link" || {
# on failure, restore the symlink
rm -rfv "$link"
ln -sfv "$reltarget" "$link"
}
done
Chạy tập lệnh này với tên liên kết làm đối số, ví dụ thông qua find . -type l -exec /path/tos/script {} +
"$var"
thành "${var}"
noop trong sh / bash. Tôi đã xóa một bashism ( [[
), phần còn lại tương thích với POSIX sh.
cp
gửi một tệp tạm thời trong cùng thư mục sau đó mv -f
tệp tạm thời đó vào bản gốc. Điều này sẽ bảo vệ chống lại các vấn đề như mọi người nhấn giữ Ctrl-C
hoặc hệ thống tập tin lấp đầy giữa các lệnh rm
và cp
(do đó ngăn chặn ngay cả cái mới hoạt ln
động). Tên tệp tạm thời rất dễ phát hiện ls -a
để dọn dẹp sau nếu cần.
abstarget=$(readlink -f "$link")
thay vì khối vụ án , nhưng đó có thể là lý do tính di động.
Có thể dễ dàng hơn khi chỉ sử dụng tar để sao chép dữ liệu vào một thư mục mới.
-H (c and r mode only) Symbolic links named on the command line will be followed; the target of the link will be archived, not the link itself.
Bạn có thể sử dụng một cái gì đó như thế này
tar -hcf - sourcedir | tar -xf - -C newdir
tar --help:
-H, --format=FORMAT create archive of the given format
-h, --dereference follow symlinks; archive and dump the files they point to
tar -hcf - sourcedir | tar -xf - -C newdir
cp -L
là giải pháp đơn giản hơn
cp
cài đặt sẽ sao chép các thư mục.
Nếu tôi hiểu bạn một cách chính xác, -L
cờ của cp
lệnh sẽ làm chính xác những gì bạn muốn.
Chỉ cần sao chép tất cả các liên kết tượng trưng và nó sẽ thay thế chúng bằng các tệp mà chúng trỏ đến.
cp -L files tmp/ && rm files && cp tmp/files .
Nếu bạn làm rõ, có lẽ bạn sẽ giúp được nhiều người hơn ...
"Dễ dàng" sẽ là một chức năng của bạn, rất có thể.
Có lẽ tôi sẽ viết một tập lệnh sử dụng tiện ích dòng lệnh "find" để tìm các tệp được liên kết tượng trưng, sau đó gọi rm và cp để xóa và thay thế tệp. Bạn có thể cũng làm tốt để có hành động được gọi bằng cách tìm kiểm tra xem còn đủ dung lượng trống trước khi di chuyển liên kết sym không.
Một giải pháp khác có thể là gắn kết hệ thống tệp được đề cập thông qua một cái gì đó ẩn các liên kết sym (như samba), sau đó chỉ cần sao chép mọi thứ ra khỏi đó. Nhưng trong nhiều trường hợp, một cái gì đó như thế sẽ giới thiệu các vấn đề khác.
Một câu trả lời trực tiếp hơn cho câu hỏi của bạn có lẽ là "có".
Chỉnh sửa: Theo yêu cầu để biết thêm thông tin cụ thể. Theo trang man để tìm , lệnh này sẽ liệt kê tất cả các tệp liên kết sym vào độ sâu của 2 thư mục, từ /:
find / -maxdepth 2 -type l -print
( điều này đã được tìm thấy ở đây )
Để tìm thấy để thực hiện một cái gì đó trên việc tìm kiếm nó:
find / -maxdepth 2 -type l -exec ./ReplaceSymLink.sh {} \;
Tôi tin rằng sẽ gọi một số tập lệnh tôi vừa tạo và chuyển vào tên tệp bạn vừa tìm thấy. Ngoài ra, bạn có thể nắm bắt kết quả tìm kiếm vào tệp (sử dụng "find [blah]> symlinks.data", v.v.) sau đó chuyển tệp đó vào tập lệnh bạn đã viết để xử lý sao chép trên bản gốc một cách duyên dáng.
-exec ./ReplaceSymLink.sh {} \;
Đây là oneliner tôi đã sử dụng: giả sử tất cả các tệp cục bộ là liên kết đến một tệp khác trong "nguồn". Bạn có thể tinh chỉnh lựa chọn tệp với các mẫu hoặc "tìm". Xin vui lòng, hiểu trước khi sử dụng.
cho f trong *; làm cp - nguồn đích-$ / $ f $ f; làm xong
Hi vọng điêu nay co ich
find . -type l -exec cp --dereference --recursive '{}' '{}'.dereferenced \;
Sẽ tạo một bản sao của từng tệp / thư mục được liên kết trong <filename>.dereferenced
đó, an toàn hơn (nếu không thuận tiện) hơn là chỉ thay thế chúng trực tiếp. Di chuyển dữ liệu đã sao chép sang tên tệp của liên kết tượng trưng được để lại như một bài tập cho người đọc.
find ./ -type l -print0|xargs -0 -n1 -i sh -c 'cp --remove-destination $(readlink "{}") "{}" '
dựa trên https://superuser.com/a/1301199/499386 của MastroGeppetto
Có rất nhiều câu trả lời hay nhưng tôi vì bạn đang tìm kiếm thứ gì đó dễ dàng
for i in *; do link=$(readlink $i) && rm $i && mv $link $i; done
Tôi gặp vấn đề tương tự với các liên kết sao chép gwenview khi bạn thường mong đợi nó theo liên kết và sao chép tệp.
Những gì tôi đã làm để 'dọn dẹp' thư mục bằng cách theo tất cả các liên kết và sao chép tất cả các tệp được trỏ vào thư mục, là tạo một thư mục cào, chạy ví dụ
"for file in `ls`; do cp -L $file scratchdir/$file; done; mv scratchdir/* ./"
Điều này quá nguy hiểm để đưa vào một kịch bản vì không có kiểm tra nhưng nó đã khắc phục vấn đề của tôi.
for f in *; do cp --remove-destination $(readlink "$f") "$f"; done
Tôi đã làm một phiên bản một dòng, vì khách sạn web của tôi không cho phép bash-scripts và nó hoạt động tốt với tôi:
before:
> find . -type l | wc -l
358
> for link in `find . -type l` ; do echo "$link : "; ls -al $link ; cp $link notalink; unlink $link; mv notalink $link ; ls -al $link; done
...
after:
> find . -type l | wc -l
0