Wciąż jestem nowicjuszem w skryptowaniu powłoki i próbuję wymyślić prosty kod. Czy ktokolwiek mógłby mi tutaj podać jakiś kierunek. Oto, czego potrzebuję.
Files in path 1: /tmp
100abcd
200efgh
300ijkl
Files in path2: /home/storage
backupfile_100abcd_str1
backupfile_100abcd_str2
backupfile_200efgh_str1
backupfile_200efgh_str2
backupfile_200efgh_str3
Teraz muszę usunąć plik 300ijkl w / tmp jakoodpowiedni plik kopii zapasowej nie jest obecny w / home / storage. Plik / tmp zawiera ponad 300 plików. Muszę usunąć pliki w / tmp, dla których nie ma odpowiednich plików kopii zapasowych, a nazwy plików w / tmp będą pasować do nazw plików w / home / storage lub katalogach w / home / storage.
Doceń swój czas i odpowiedź.
Odpowiedzi:
0 dla odpowiedzi № 1Możesz rozwiązać to przez
- tworzenie listy plików w
/home/storage
- testowanie każdej nazwy pliku
/tmp
aby zobaczyć, czy jest na liście/home/storage
Biorąc pod uwagę znaczniki powłoki linux +, można użyć bash:
- zrób listę plików z
/home/storage
na tablica asocjacyjna - uczynić z indeksu tablicy nazwę pliku
Oto przykładowy skrypt do zilustrowania ($1
i $2
są parametrami, które należy przekazać do skryptu, tj. /home/storage
i /tmp
):
#!/bin/bash
declare -A InTarget
while read path
do
name=${path##*/}
InTarget[$name]=$path
done < <(find $1 -type f)
while read path
do
name=${path##*/}
[[ -z ${InTarget[$name]} ]] && rm -f $path
done < <(find $2 -type f)
Wykorzystuje dwie interesujące funkcje powłoki:
name=${path##*/}
jest Powłoka POSIX funkcja, która umożliwia wykonanie skryptubasename
funkcja bez dodatkowego procesu (na nazwę pliku). To sprawia, że skrypt jest szybszy.done < <(find $2 -type f)
jest funkcja bash co pozwala skryptowi odczytać listę nazw plików zfind
bez wykonywania przypisań do tablicyw podprocesie. Powodem użycia tej funkcji jest to, że jeśli tablica jest aktualizowana w podprocesie, nie ma to wpływu na wartość tablicy w skrypcie przekazywanym do drugiej pętli.
Dla powiązanej dyskusji:
0 dla odpowiedzi nr 2
Możesz również podejść do usuwania za pomocą grep
także. Możesz zapętlić pliki w /tmp
sprawdzanie za pomocą ls
podłączony do grep
i usuwanie, jeśli nie ma dopasowania:
#!/bin/bash
[ -z "$1" -o -z "$2" ] && { ## validate input
printf "error: insufficient input. Usage: %s tmpfiles storagen" ${0//*//}
exit 1
}
for i in "$1"/*; do
fn=${i##*/} ## strip path, leaving filename only
## if file in backup matches filename, skip rest of loop
ls ${2}* | grep -q $fn &>/dev/null && continue
printf "removing %sn" "$i"
# rm "$i" ## remove file
done
Uwaga: faktyczne usunięcie zostało skomentowane powyżej, przetestuj i upewnij się, że nie ma żadnych niezamierzonych konsekwencji przed utworzeniem faktycznego usunięcia. Nazwij to przechodząc ścieżką do tmp
(bez ciągnięcia /
) jako pierwszy argument iz /home/storage
jako drugi argument:
$ bash scriptname /path/to/tmp /home/storage