มีวิธีง่าย ๆ ในการแทนที่ลิงก์สัญลักษณ์ทั้งหมดด้วยไฟล์ที่ลิงก์ไปหรือไม่?
มีวิธีง่าย ๆ ในการแทนที่ลิงก์สัญลักษณ์ทั้งหมดด้วยไฟล์ที่ลิงก์ไปหรือไม่?
คำตอบ:
สำหรับคำจำกัดความของ "ง่าย":
#!/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
เรียกใช้สคริปต์นี้ด้วยชื่อลิงก์เป็นอาร์กิวเมนต์เช่นผ่าน find . -type l -exec /path/tos/script {} +
"$var"
ไป"${var}"
เป็น noop ในการดวลจุดโทษ / ทุบตี ฉันลบหนึ่ง bashism ( [[
) ส่วนที่เหลือเข้ากันได้กับ POSIX sh
cp
ยังไฟล์ชั่วคราวในไดเรกทอรีเดียวกันจากนั้นmv -f
ไฟล์ชั่วคราวนั้นจะเป็นต้นฉบับ นี้ควรป้องกันปัญหาเช่นคนที่ถือลงCtrl-C
หรือระบบแฟ้มเติมขึ้นระหว่างrm
และcp
คำสั่ง (จึงป้องกันได้ใหม่ln
จากการทำงาน) ชื่อไฟล์ชั่วคราวนั้นง่ายls -a
ต่อการทำความสะอาดในภายหลังหากจำเป็น
abstarget=$(readlink -f "$link")
แทนกรณีบล็อก แต่มันอาจจะเป็นเหตุผลในการพกพา
อาจจะง่ายกว่าเพียงแค่ใช้ tar เพื่อคัดลอกข้อมูลไปยังไดเรกทอรีใหม่
-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.
คุณสามารถใช้สิ่งนี้
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
เป็นวิธีแก้ปัญหาที่ง่ายกว่า
cp
การใช้งานไม่ได้ทั้งหมดจะคัดลอกไดเรกทอรี
หากฉันเข้าใจคุณอย่างถูกต้อง-L
ค่าสถานะของcp
คำสั่งควรทำสิ่งที่คุณต้องการ
เพียงคัดลอกลิงก์ทั้งหมดและมันจะแทนที่ด้วยไฟล์ที่พวกเขาชี้ไปที่
cp -L files tmp/ && rm files && cp tmp/files .
ถ้าคุณชี้แจงคุณอาจจะช่วยผู้คนมากขึ้น ...
"ง่าย" จะเป็นหน้าที่ของคุณ
ฉันอาจจะเขียนสคริปต์ที่ใช้ยูทิลิตีบรรทัดคำสั่ง "find" เพื่อค้นหาไฟล์ที่มีสัญลักษณ์เชื่อมโยงจากนั้นเรียก rm และ cp เพื่อลบและแทนที่ไฟล์ คุณน่าจะทำได้ดีหากมีการดำเนินการที่เรียกว่าโดยการตรวจสอบการค้นหาว่ามีพื้นที่ว่างเหลือพอก่อนที่จะย้ายลิงก์ sym ด้วย
วิธีแก้ไขปัญหาอื่นอาจเป็นการเมานต์ระบบไฟล์ที่เป็นปัญหาผ่านสิ่งที่ซ่อนลิงก์ sym (เช่น samba) จากนั้นคัดลอกทุกอย่างออก แต่ในหลายกรณีบางอย่างเช่นนั้นจะแนะนำปัญหาอื่น ๆ
คำตอบที่ตรงกับคำถามของคุณน่าจะเป็น "ใช่"
แก้ไข: ตามคำขอสำหรับข้อมูลที่เฉพาะเจาะจงมากขึ้น ตามหน้า man for findคำสั่งนี้จะแสดงรายการไฟล์ sym ลิงก์ทั้งหมดในความลึก 2 ไดเรกทอรีจาก /:
find / -maxdepth 2 -type l -print
( พบที่นี่ )
หากต้องการค้นหาเพื่อดำเนินการบางอย่างกับการค้นหา:
find / -maxdepth 2 -type l -exec ./ReplaceSymLink.sh {} \;
ฉันเชื่อว่าจะเรียกสคริปต์ที่ฉันเพิ่งสร้างขึ้นและส่งชื่อไฟล์ที่คุณเพิ่งพบ หรือคุณสามารถจับค้นหาผลลัพธ์ไปยังไฟล์ (ใช้ "find [blah]> symlinks.data" ฯลฯ ) จากนั้นส่งไฟล์นั้นไปยังสคริปต์ที่คุณเขียนขึ้นเพื่อจัดการกับการคัดลอกต้นฉบับอย่างงดงาม
-exec ./ReplaceSymLink.sh {} \;
นี่คือออนไลเนอร์ที่ฉันใช้: ถือว่าไฟล์ในเครื่องทั้งหมดเป็นลิงก์ไปยังไฟล์อื่นใน "แหล่งที่มา" คุณสามารถปรับแต่งการเลือกไฟล์ด้วยรูปแบบหรือ "ค้นหา" โปรดเข้าใจก่อนใช้
สำหรับ f ใน *; ทำซีพี - ลบแหล่งที่มาปลายทาง / $ f $ f; เสร็จแล้ว
หวังว่านี่จะช่วยได้
find . -type l -exec cp --dereference --recursive '{}' '{}'.dereferenced \;
จะทำสำเนาของไฟล์ / โฟลเดอร์ symlinked แต่ละไฟล์<filename>.dereferenced
ซึ่งปลอดภัยกว่า (ถ้าสะดวกน้อยกว่า) แทนที่จะทำการแทนที่โดยตรง การย้ายข้อมูลที่คัดลอกไปยังชื่อไฟล์ของ symlink นั้นจะเป็นแบบฝึกหัดสำหรับผู้อ่าน
การใช้แนวคิดก่อนหน้านี้บางคำสั่งต่อไปนี้จะแทนที่ symlink ทุกครั้งด้วยสำเนาของต้นฉบับ:
find . -type l -exec bash -c "echo 'Replacing {} ...'; cp -LR '{}' '{}'.dereferenced; rm '{}'; mv '{}'.dereferenced '{}'" \;
find ./ -type l -print0|xargs -0 -n1 -i sh -c 'cp --remove-destination $(readlink "{}") "{}" '
อ้างอิงจาก/superuser//a/1301199/499386จาก MastroGeppetto
มีคำตอบที่ดีมากมาย แต่ฉันเนื่องจากคุณกำลังมองหาบางสิ่งที่ง่าย
for i in *; do link=$(readlink $i) && rm $i && mv $link $i; done
ฉันมีปัญหาเดียวกันกับการคัดลอกลิงก์ gwenview เมื่อคุณคาดหวังว่ามันจะตามลิงค์และคัดลอกไฟล์
สิ่งที่ฉันทำเพื่อ 'ทำความสะอาด' ไดเรกทอรีโดยทำตามลิงค์ทั้งหมดและคัดลอกไฟล์ชี้ไปยังไดเรกทอรีทั้งหมดได้สร้างไดเรกทอรีรอยขีดข่วนเรียกใช้เช่น
"for file in `ls`; do cp -L $file scratchdir/$file; done; mv scratchdir/* ./"
มันอันตรายเกินไปที่จะใส่สคริปต์เนื่องจากไม่มีการตรวจสอบ แต่แก้ไขปัญหาของฉันได้
for f in *; do cp --remove-destination $(readlink "$f") "$f"; done
ฉันทำรุ่นหนึ่งบรรทัดเนื่องจากเว็บโรงแรมของฉันไม่อนุญาตให้ใช้สคริปต์ทุบตีและทำงานได้ดีสำหรับฉัน:
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