Câu hỏi Script để quét qua một số thư mục, tìm kiếm một tập tin và sao chép nó vào một tên mới


Hy vọng rằng ai đó có thể giúp tôi ở đây. Tôi cần phải làm sạch một số dữ liệu trên một khoảng thời gian thường xuyên nhưng ngắn làm nó bằng tay tôi đã không đưa ra một giải pháp tốt.

Đây là luồng mà tôi thực hiện theo cách thủ công.

Tôi có một thư mục cấp cao nhất được gọi là "Dữ liệu", dưới nó tôi có một số thư mục, khoảng 100 mà đến và đi. Dưới mỗi người trong số đó có một tập tin gọi là folder.jpg. Ngoài ra còn có các thư mục con trong thư mục này nhưng tôi cần nó để dừng lại ở cấp cơ sở.

Lý tưởng nhất, những gì nó sẽ làm là tìm kiếm thông qua mỗi thư mục và nhìn để xem nếu có một tập tin gọi là show.jpg trong đó, nếu có bỏ qua các thư mục và di chuyển trên. Nếu không, hãy tìm trong cùng một thư mục cho một tệp có tên là folder.jpg và sao chép nó vào một tệp mới có tên là show.jpg.

Âm thanh dễ dàng trong tâm trí tôi.


1
2017-10-08 18:44


gốc


Bạn đã gắn thẻ VBScript này - nó có phải là trong VBScript, hay lô / PowerShell sẽ làm gì? Phiên bản Windows nào? - Iszi
"Nghe có vẻ dễ dàng trong tâm trí tôi." - Bạn đã viết gì cho đến nay? - EBGreen
PowerShell sẽ hoạt động. - JoshFink


Các câu trả lời:


Đây là một tập lệnh sẽ hoạt động trong PowerShell, nhưng tôi chưa thực hiện kiểm tra. Điều này giả định thư mục dữ liệu của bạn nằm trong thư mục gốc của C :.

Get-ChildItem C:\Data\*\* | Where-Object {$_.Name -eq 'folder.jpg'} | ForEach-Object {
    $CurrentFolder = $_.Directory
    if ((Test-Path "$CurrentFolder\show.jpg") -eq $false)
    {Copy-Item $_ "$CurrentFolder\show.jpg"}
    Remove-Variable CurrentFolder
}

Phá vỡ:

Thông số được gán cho Get-ChildItem yêu cầu nó trả về tất cả các đối tượng được tách ra từ C: \ Data theo một cấp thư mục.

Where-Object được sử dụng để lọc các kết quả này xuống chỉ các tệp có tên folder.jpg.

ForEach-Object được sử dụng để lặp qua các kết quả còn lại.

Để xử lý mỗi thư mục.jpg, trước tiên chúng ta đặt một biến ($CurrentFolder) để chứa giá trị của đường dẫn thư mục của nó.

Sau đó, chúng tôi sử dụng Test-Path để xem liệu show.jpg có bị thiếu trong cùng một thư mục hay không.

Nếu show.jpg không được tìm thấy, Copy-Item sẽ sao chép folder.jpg to show.jpg.

Dọn dẹp $CurrentFolder biến với Remove-Variable là tùy chọn, nhưng thực hành tốt.

Kịch bản cũng có thể được cắt giảm xuống chỉ để điều này, nếu bạn đang tìm kiếm một "một lớp lót":

ls C:\Data\*\*|?{$_.Name -eq 'folder.jpg'}|%{$c=$_.Directory;if(!(Test-Path "$c\show.jpg")){cp $_ "$c\show.jpg"}}

ls là một bí danh cài sẵn cho Get-ChildItem

? là một bí danh cài sẵn cho Where-Object

% là một bí danh cài sẵn cho ForEach-Object

$CurrentFolder được rút ngắn xuống $c

Kết quả của Test-Path "$c\show.jpg" đã bị từ chối (nghĩa là: TRUE sẽ là FALSE và ngược lại) bằng cách đóng gói nó trong !(). Nếu một biểu thức đánh giá trực tiếp đến một Boolean, và bạn muốn một khối mã chạy trên TRUE, bạn không cần phải bao gồm -eq $true bên trong if tuyên bố.

cp là một bí danh cài sẵn cho Copy-Item

Remove-Variable đã bị bỏ qua. (Mặc dù bạn có thể sử dụng bí danh cài sẵn rv nếu bạn thích.)


2
2017-10-08 19:29



Tôi đã có thể làm cho nó chạy nhưng đặt parens xung quanh 'Test-Path' $ CurrentFolder \ show.jpg "'vì vậy nó trông giống như' if ((Test-Path" $ CurrentFolder \ show.jpg ") -eq $ false) ' - JoshFink
BTW, tôi đã dọn dẹp "câu trả lời" khác của mình. Đánh giá cao tất cả sự giúp đỡ. Điều này làm cho ngày của tôi. - JoshFink
@ JoshFink Ah, dấu ngoặc đơn là cần thiết đôi khi quá. Nắm bắt tốt. - Iszi
bạn có thể cập nhật mã gốc khi bạn có cơ hội không. Cảm ơn vì sự giúp đỡ - JoshFink