Как удалить файлы Temp без изменения времени модификации каталога?

setopt выводит отклонение от текущего режима эмуляции. appendhistory установлен по умолчанию в эмуляции zsh.

Для отображения состояния всех опций можно использовать set -o.

Цитирую документ:

 Если аргументы не указаны, выводятся имена всех опций, установленных в данный момент.
 печатаются имена всех установленных в данный момент опций. Форма выбрана таким образом, чтобы минимизировать
 отличия от опций по умолчанию для текущей эмуляции (эмуляцией по умолчанию является
 эмуляцией по умолчанию является родной zsh, показанный как  в *примечании
 Описание опций::). Параметры, включенные по умолчанию для
 эмуляции, показываются с префиксом no, только если они выключены, в то время как
 другие опции показываются без префикса no и только в том случае.
 включены. В дополнение к опциям, измененным из состояния по умолчанию пользователем
 пользователем, любые опции, активируемые автоматически оболочкой (например
 например, SHIN_STDIN или INTERACTIVE) будут показаны в списке. Формат
 формат дополнительно изменяется опцией KSH_OPTION_PRINT, однако
 обоснование выбора опций с префиксом no или без него
 остается неизменным и в этом случае.
5
22.05.2018, 23:17
4 ответа

Deberá restablecer la marca de tiempo en el directorio después de eliminar los archivos. Suponiendo herramientas GNU,algo como esto debería funcionar:

mtime=$(stat -c %y dir)            # get the timestamp, store in $mtime
rm dir/somefile dir/someotherfile  # do whatever you need
touch -d "$mtime" dir              # set the timestamp back

Eso restablece las marcas de tiempo de modificación(mtime)y acceso(atime)en el directorio a la marca de tiempo de modificación original, pero también establece la marca de tiempo de cambio(ctime)a la hora actual. Cambiar el ctimees inevitable, pero probablemente no le importe o atime.

3
27.01.2020, 20:40

Команда touchпредоставляет опцию -r, которая позволяет вам коснуться файла с теми же временными метками, что и эталонный файл. Таким образом, вы можете сделать это:

touch -r /dir/somefile /tmp/_thetimestamps  # save the timestamps in /tmp/_thetimestamps
rm /dir/somefile                            # do whatever you need
touch -r /tmp/_thetimestamps /dir           # set the timestamps back

Линукс Человек:

-r, --reference=FILE
      use this file's times instead of current time

Unix Человек:

-r       Use the access and modifications times from the specified file
         instead of the current time of day.
2
27.01.2020, 20:40

Вот версия отличного ответа ikkachu на Python:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Removes a file or directory while preserving the modification time (mtime) of
the parent directory.
Pure-python implementation.
"""

import argparse
import logging
import os
import platform
import re
import shutil
import stat
import sys

log_formatter = logging.Formatter('%(asctime)s, %(levelname)s %(message)s')

logging.basicConfig(level=logging.INFO, formatter=log_formatter)
logger = logging.getLogger(__name__)

def parse_opts(args):
    parser = argparse.ArgumentParser(
        description='Removes a file or directory while preserving the modification time (mtime) of the parent directory.',
        argument_default=False,
    )
    parser.add_argument('-v', '--verbose', type=bool, help='Activate verbose log output')
    parser.add_argument('paths', type=str, nargs='+', help='Filesystem path(s) to remove')

    opts = parser.parse_args(args)
    if opts.verbose:
        logger.setLevel(logging.DEBUG)

    return opts

def rm_and_preserve_parent_mtime(path):
    if path in (os.sep, '', '.', '..') or (platform.system() == 'Windows' and re.match(r'^[A-Z]:%s?' % (os.sep,), path)):
        raise Exception('Invalid path, must have a parent directory')

    parent = os.path.dirname(path)

    if path == parent:
        raise Exception('Invalid path, parent directory cannot be the same value')

    st = os.stat(parent)
    atime = st[stat.ST_ATIME]
    mtime = st[stat.ST_MTIME]

    logger.debug('Removing path: %s', path)
    try:
        if os.path.isfile(path):
            os.remove(path)
        elif os.path.isdir(path):
            os.rmdir(path)
        else:
            raise Exception('Path "%s" is not a file or directory' % (path,))
    except OSError:
        shutil.rmtree(path)

    os.utime(parent, (atime, mtime))

def main(paths):
    try:
        for path in paths:
            rm_and_preserve_parent_mtime(path)
        return 0
    except BaseException:
        logger.exception('Caught exception in main')
        return 1

if __name__ == '__main__':
    opts = parse_opts(sys.argv[1:])
    sys.exit(main(opts.paths))
0
27.01.2020, 20:40

Вот версия отличного ответа ikkachu на Python:

https://gist.github.com/jaytaylor/ea1b6082ea5bcea7a6b65518d91238f5

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Removes a file or directory while preserving the modification time (mtime) of
the parent directory.

Pure-python implementation.

See also:
    https://unix.stackexchange.com/a/565595/22709
"""

import argparse
import logging
import os
import platform
import re
import shutil
import stat
import sys

log_formatter = logging.Formatter('%(asctime)s, %(levelname)s %(message)s')

logging.basicConfig(level=logging.INFO, formatter=log_formatter)
logger = logging.getLogger(__name__)

def parse_opts(args):
    parser = argparse.ArgumentParser(
        description='Removes a file or directory while preserving the modification time (mtime) of the parent directory.',
        argument_default=False,
    )
    parser.add_argument('-f', '--force', default=False, action='store_true', help='Ignore nonexistent files and arguments')
    parser.add_argument('-i', '--interactive', default=False, action='store_true', help='Prompt for confirmation before taking action on a target')
    parser.add_argument('--no-preserve-root', default=False, action='store_true', help="Do not treat '/' specially")
    parser.add_argument('-r', '--recursive', default=False, action='store_true', help='Remove directories and their contents recursively')
    parser.add_argument('-v', '--verbose', default=False, action='store_true', help='Display verbose log output')
    parser.add_argument('paths', type=str, nargs='+', help='Filesystem path(s) to remove')

    opts = parser.parse_args(args)
    if opts.verbose:
        logger.setLevel(logging.DEBUG)

    return opts

# n.b. Use the appropriate input function depending on whether the runtime
#      environment is Python version 2 or 3.
_input_fn = input if sys.version_info > (3, 0) else raw_input

def _prompt_for_confirmation(path, opts):
    if not opts.interactive:
        return True

    response = _input_fn('Permanently remove "%s"? (Y/n)' % (path,))
    return response in ('Y', 'y')

def require_write_permissions(path):
    parent = os.path.dirname(path)
    if not os.access(parent, os.W_OK):
        raise Exception('Missing necessary write permission for parent directory "%s"; operation aborted' % (parent,))

def rm_preserving_parent_mtime(path, opts):
    """
    Deletes the specified path, and restores the filesystem access and modified
    timestamp values afterward removing path.

    IMPORTANT
    ---------
    Take note of the permission test before removing the target. These checks
    verify write access to parent's parent.

    Without the check, there is a risk that the file will be removed and then
    setting mtime fails.  When this happens, the entire purpose of this program is defeated.
    """
    if not opts.no_preserve_root and (path == os.sep or (platform.system() == 'Windows' and re.match(r'^[A-Z]:%s?' % (os.sep,), path))):
        raise Exception('Cowardly refusing to operate on root path')

    if path in ('', '.', '..'):
        raise Exception('Invalid path "%s", must have a parent directory' % (path,))

    parent = os.path.dirname(path)

    if path == parent:
        raise Exception('Invalid path, parent directory="%s" should not equal path="%s"' % (parent, path))

    st = os.stat(parent)
    atime = st[stat.ST_ATIME]
    mtime = st[stat.ST_MTIME]

    modified = False

    try:
        if os.path.isfile(path):
            require_write_permissions(parent)
            if _prompt_for_confirmation(path, opts):
                logger.debug('Removing file "%s"' % (path,))
                modified = True
                os.remove(path)
        elif os.path.isdir(path):
            if not opts.recursive:
                raise Exception('Cannot remove "%s": Is a directory' % (path,))
            require_write_permissions(parent)
            if _prompt_for_confirmation(path, opts):
                logger.debug('Removing directory "%s"' % (path,))
                modified = True
                shutil.rmtree(path)
        else:
            raise Exception('Path "%s" is not a file or directory' % (path,))
    finally:
        if modified:
            logger.debug('Restoring access and modification timestamps for parent="%s"' % (parent,))
            os.utime(parent, (atime, mtime))

def main(paths, opts):
    try:
        for path in paths:
            rm_preserving_parent_mtime(path, opts)
        return 0
    except BaseException:
        logger.exception('Caught exception in main')
        if opts.force:
            return 0
        return 1

if __name__ == '__main__':
    opts = parse_opts(sys.argv[1:])
    sys.exit(main(opts.paths, opts))

Полные решения для перемещения или удаления файлов с сохранением mtime родительского каталога см. в этих скриптах Python:https://gist.github.com/jaytaylor/e2e0b53baf224f4e973b252370499de7

-1
03.02.2020, 17:05

Теги

Похожие вопросы