it-swarm-eu.dev

Jak vypsat seznam souborů, které byly změněny v určitém časovém období?

Jak mohu rekurzivně vypsat všechny soubory, které byly změněny mezi 22.12.2011 a 24.12.2011?

40
clamp

Obecně řečeno, když hledáte soubory v adresáři a jeho podadresářích rekurzivně, použijte find.

Nejjednodušší způsob, jak určit časové období pomocí find, je vytvořit soubory na hranici rozsahu a použít -newer predikát.

touch -t 201112220000 start
touch -t 201112240000 stop
find . -newer start \! -newer stop

Pomocí Gillesova řešení a po přečtení man find (1) znovu jsem našel jednodušší řešení. Nejlepší volbou je -newerXY. Lze použít příznaky m a t.

m   The modification time of the file reference
t   reference is interpreted directly as a time

Takže řešení je

find . -type f -newermt 20111222 \! -newermt 20111225

Dolní mez včetně a horní mez je exkluzivní, takže jsem k ní přidal 1 den! A je rekurzivní. Funguje dobře na nalezení v4.5.9.

38
TrueY

Kromě již uvedených odpovědí můžete také přímo zadat data:

find -type f -newermt "2011-12-22" \! -newermt "2011-12-24"

nebo

find -type f -newermt "2011-12-22 00:00:00" \! -newermt "2011-12-24 13:23:00"

pokud navíc chcete určit čas.

15
student

Za předpokladu, že nepotřebujete přesnost na sekundy, mělo by to fungovat.

find . -type f -mmin -$(((`date +%s`-`date -d 20111222 +"%s"`)/60)) \! -mmin +$(((`date +%s`-`date -d 20111224 +"%s"`)/60))

EDIT: Změněno cmin na mmin za komentář @ Eelvex. ÚPRAVA: '\!' chybějící

6
onur güngör

find může trvat datetime ve formátu ISO, takže například pro server na UTC byste mohli zadat offset o několik hodin od místa, kde jste. Tím se také postará o přidání dne, protože také porovnáváte čas:

find -type f -newermt 20111224T0800 \! -newermt 20111225T0800
3
Alex Young

Vezměte prosím na vědomí, že otázka označená jako duplicitní, a proto se na ni nemůže přímo odpovědět, je proto důvodem, proč sem přispívám. Tato odpověď slouží k zodpovězení otázky „potřeba přesunout soubory do jiné složky na základě data vytvoření [duplikát]“

Odpovědi jsou rozumné, ale existovala určitá omezení s čistě vyhledávacím příkazem. Napsal jsem tento skript Shell, abych prošel adresář s tolika soubory v něm, že souborový systém roubí na metadata, která se snaží provést ls. Některé systémy * nix navíc při spuštění ls odstraní příliš mnoho chyb argumentů.

Příkaz find je velmi silný a začal jsem s metodami, které jsou uvedeny, ale měl jsem v tomto adresáři tolik let dat, že jsem musel opakovaně předávat všechny soubory. Tím se vytvoří každý soubor zbytečně zbytečný. Zkoušel jsem dělat jednu obrazovku ročně a provozovat více nálezů, ale to vedlo k mnoha chybám z každého nálezu a soubory by zmizely, když by jeden z nálezů přesunul.

Skript My Shell přesune soubor do cílového adresáře se čtyřmístným rokem a dvoumístným měsícem. Lze jej snadno rozšířit na dvouciferný den zrušením pár řádků a komentováním jejich protějšků. Věřím, že je to efektivnější, protože to bylo provedeno pohyby v jednom průchodu najít, takže více příkazů najít a průchody přes adresář jsou zbytečné.

#!/bin/bash
#We want to exit if there is no argument submitted
if [ -z "$1" ]
then
  echo no input file
  exit
fi

#destDir should be set to where ever you want the files to go
destDir="/home/user/destination"

#Get the month and year of modification time
#--format %y returns the modification date in the format:
# 2016-04-26 12:40:48.000000000 -0400
#We then take the first column, split by a white space with awk
date=`stat "$1" --format %y | awk '{ print $1 }'`

#This sets the year variable to the first column split on a - with awk
year=`echo $date | awk -F\- '{print $1 }'`
#This sets the month variable to the second column split on a - with awk
month=`echo $date | awk -F\- '{print $2 }'`
#This sets the day variable to the third column split on a - with awk
#This is commented out because I didn't want to add day to mine
#day=`echo $date | awk -F\- '{print $3 }'`

#Here we check if the destination directory with year and month exist
#If not then we want to create it with -p so the parent is created if
# it doesn't already exist
if [ ! -d $destDir/$year/$month ]
then
  mkdir -p $destDir/$year/$month || exit
fi

#This is the same as above but utilizes the day subdirectory
#Uncommented this out and comment out the similar code above
#if [ ! -d $destDir/$year/$month/$day ]
#then
#  mkdir -p $destDir/$year/$month$day || exit
#fi

#Echoing out what we're doing
#The uncommented is for just year/month and the commented line includes day
#Comment the first and uncomment the second if you need day
echo Moving $1 to $destDir/$year/$month
#echo Moving $1 to $destDir/$year/$month/$day

#Move the file to the newly created directory
#The uncommented is for just year/month and the commented line includes day
#Comment the first and uncomment the second if you need day
mv "$1" $destDir/$year/$month
#mv "$1" $destDir/$year/$month/$day

Po uložení a provedení spustitelného můžete tento skript nazvat následujícím způsobem.

find /path/to/directory -type f -exec /home/username/move_files.sh {} \;

Nemusíte se starat o nastavení možnosti newermt for find, protože vše, co poskytuje find, je jediné spuštění na nalezený soubor a skript provede všechna rozhodnutí.

Nezapomeňte, že pokud nevyberete -typ f, bude to posouvat adresáře a to pravděpodobně způsobí problémy. Můžete také použít -typ d, pokud chcete přesouvat pouze adresáře. Pokud nenastavíte typ, téměř jistě dojde k nežádoucímu chování.

Nezapomeňte, že tento skript byl přizpůsoben my potřebám. Možná budete chtít jednoduše použít můj konstrukt jako inspiraci pro lépe vyhovující skript pro vaše potřeby. Děkuju!

Úvahy: Účinnost příkazu lze VÝRAZNĚ zlepšit povolením neomezeného počtu argumentů projít skriptem. Ve skutečnosti je to relativně snadné, pokud předáte proměnnou $ @. Rozšíření této funkce by nám například umožnilo použít funkci find -exec + nebo využít xargs. Mohu to rychle implementovat a vylepšit svou vlastní odpověď, ale to je začátek.

Protože se jednalo o jednorázový skript, existuje pravděpodobně mnoho vylepšení, která lze provést. Hodně štěstí!

0
Vex Mage