Shell-Script

根據某種模式選擇和移動獨特的文件

  • October 16, 2020

我有一個 Linux 機器上的文件列表,這些文件在某個日期有所不同,所以我必須搜尋唯一的文件並需要將它們放在其他目錄中。這裡的“唯一”是指直到第二個的文件名,_所以在下面的例子中。100001_ABC``100001_XYZ

100001_ABC_25Sep2020_1200-25Sep2020_1300.csv  
100001_XYZ_30Sep2020_1300-30Sep2020_1400.csv  
100001_XYZ_30Sep2020_1400-30Sep2020_1500.csv

我希望將唯一命名的放在此目錄下:

/home/vikrant_singh_rana/uniquefiles/

該腳本應僅複製以下文件:

100001_ABC_25Sep2020_1200-25Sep2020_1300.csv  
100001_XYZ_30Sep2020_1300-30Sep2020_1400.csv  

這是我的shell腳本

#!/bin/bash
set +o posix
#reading file names into file_array
readarray -t file_array < <(
   cd "/home/vikrant_singh_rana/unzipfiles"
   printf "%s\n" * | cut -d"_" -f2 | cut -d"-" -f1 | sort -u )

#print items of array
printf '%s\n' "${file_array[@]}"


for i in "${file_array[@]}"; do
       #echo $i
       find /home/vikrant_singh_rana/unzipfiles/ -type f -name "*$i*.csv" -exec awk '!seen[$0]++' {} +
done

該腳本可以正確找到唯一名稱,但我找不到如何將它們移動到另一個目錄。

zsh.

typeset -A files
for f (*_*_*.csv(.On)) files[${(M)f#*_*_}]=$f
mv -- $files target-directory/

.glob 限定符限制為正常文件,同時以On相反的順序排序,以便最後關聯數組包含給定鍵的按字母順序排列的第一個文件(此處為第二個部分_)。

而不是詞法順序,您可能希望o通過m修改時間來代替(考慮例如在詞法順序中100001_XYZ_01Oct2020_0000-01Oct2020_0100會出現在前面 ),通過替換(將文件從最新到最舊排序),以便最終將最舊的文件移動為與按詞彙順序排在第一位的那個相反。100001_XYZ_30Sep2020_2200-30Sep2020_2300``On``om

或者您可以根據文件名中的第一個時間戳定義排序順序:

zmodload zsh/datetime
bydate() strftime -rs REPLY %d%b%Y_%H%M ${${REPLY%-*}#*_*_}

並使用nO+bydate代替On/ om

使用bashGNU 工具,您可以做一些接近的事情(不限於正常文件,但不按修改時間排序):

shopt -s failglob
printf '%s\0' *_*_*.csv | sort -zsmut_ -k1,2 | xargs -r0 mv -t target-dir --

(所有-z, -s, -r, -0,-t都是 GNU 擴展)。

從文件名中提取的時間戳排序可以通過以下方式完成:

printf '%s\0' *_*_*.csv |
                  #  key   year       month      day        HHMM
 LC_ALL=C sort -zt_ -k1,2 -k3.6,3.9n -k3.3,3.5M -k3.1,3.2n -k3.11,3.14n |
 LC_ALL=C sort -zsmut_ -k1,2 |
 xargs -r0 mv -t target-dir 

如果作為,您想要第一次和第二次出現之間的部分_,請替換${(M)f#*_*_}${${f#*_}%%_*}(或${${(s[_])f}[2]})或-k1,2替換為-k2,2

這是任何文件名的解決方案:

target_dir="path/to/dir"

find -maxdepth 1 -type f -name '*.csv' -print0 | sort -z | awk '
   BEGIN {RS=ORS="\0"; FS=OFS="_"}
   !seen[$2]++' | xargs -r0 echo mv -t "$target_dir" --

我們通過管道使用空分隔符來保護文件名,sort按字母順序獲取它們並GNU awk排除重複項。測試它,如果它列印出合理的移動命令,請刪除echo以執行它。

(以上所有用於空分隔的都是 GNU 擴展-z等)


這更簡單,因為如果您的文件名非常好,您可以簡單地執行以下操作:

ls -1 *.csv | awk -F_ '!seen[$2]++' | xargs -d'\n' echo mv -t target/dir --

請注意,glob 按字母順序獲取文件。

引用自:https://unix.stackexchange.com/questions/614783