input: 
  from typing import List, Dict, Optional, Union
  import os
  import json
  import logging
  import fcntl
  from jsub.util import safe_mkdir, safe_rmdir
  from jsub.error import RepoReadError, TaskNotFoundError
  
  ID_FILENAME = 'id'
  
  class FileSystem(object):
      def __init__(self, param: Dict[str, Union[str, int]]):
          self.__jsub_dir = os.path.expanduser(param.get('taskDir', '~/jsub/'))
          self.__logger = logging.getLogger('JSUB')
          self.__json_format = param.get('format', 'compact')
  
      def save_task(self, data: Dict[str, Union[str, int]]) -> None:
          """Save task data into the file system.
          If the dictionary does not include an 'id' key, generate one and add it.
          Then save the task data into a file in the directory named after the task ID.
          
          >>> fs = FileSystem({'taskDir': '~/jsub/'})
          >>> fs.save_task({'name': 'task1', 'details': 'some details'})
          """
          if 'id' not in data:
              safe_mkdir(self.__jsub_dir)
              data['id'] = self.__new_task_id()
          safe_mkdir(os.path.join(self.__jsub_dir, str(data['id']), 'taskInfo'))
          task_path = os.path.join(self.__jsub_dir, str(data['id']), 'taskInfo', 'repo')
  
          data_str = self.__json_str(data)
          with open(task_path, 'a+') as f:
              fcntl.flock(f, fcntl.LOCK_EX)
              f.seek(0)
              f.truncate()
              f.write(data_str)
  
      def delete_task(self, task_id: int) -> None:
          """Delete task data by the given task ID.
          Removes the subdirectory containing the task data.
          
          >>> fs = FileSystem({'taskDir': '~/jsub/'})
          >>> fs.save_task({'id': 1, 'name': 'task1'})
          >>> fs.delete_task(1)
          """
          safe_rmdir(os.path.join(self.__jsub_dir, str(task_id)))
  
      def find_by_id(self, task_id: int) -> Dict[str, Union[str, int]]:
          """Find task data by the given task ID.
          Returns the task data as a dictionary.
          
          >>> fs = FileSystem({'taskDir': '~/jsub/'})
          >>> fs.save_task({'id': 1, 'name': 'task1'})
          >>> fs.find_by_id(1)
          {'id': 1, 'name': 'task1'}
          """
          return self.task_data(task_id)
  
      def find_by_ids(self, task_ids: List[int]) -> List[Dict[str, Union[str, int]]]:
          """Find task data by a list of task IDs.
          Returns a list of task data dictionaries.
          
          >>> fs = FileSystem({'taskDir': '~/jsub/'})
          >>> fs.save_task({'id': 1, 'name': 'task1'})
          >>> fs.save_task({'id': 2, 'name': 'task2'})
          >>> fs.find_by_ids([1, 2])
          [{'id': 1, 'name': 'task1'}, {'id': 2, 'name': 'task2'}]
          """
          all_data = []
          for task_id in task_ids:
              try:
                  td = self.task_data(task_id)
                  all_data.append(td)
              except RepoReadError as e:
                  self.__logger.debug(e)
          return all_data
  
      def all_task_data(self, order: str = 'asc') -> List[Dict[str, Union[str, int]]]:
          """Find all task data.
          Returns a list of all task data dictionaries. The list is sorted by ID in ascending order
          by default, or descending order if the 'order' parameter is set to 'desc'.
          
          >>> fs = FileSystem({'taskDir': '~/jsub/'})
          >>> fs.save_task({'id': 1, 'name': 'task1'})
          >>> fs.save_task({'id': 2, 'name': 'task2'})
          >>> fs.all_task_data()
          [{'id': 1, 'name': 'task1'}, {'id': 2, 'name': 'task2'}]
          """
          task_ids = [d for d in os.listdir(self.__jsub_dir) if os.path.isdir(os.path.join(self.__jsub_dir, d))]
          task_ids.sort(key=int, reverse=(order == 'desc'))
          return self.find_by_ids(task_ids)
  
      def task_data(self, task_id: int) -> Optional[Dict[str, Union[str, int]]]:
          """Get task data for the given task ID without raising an error if the data is not found.
          Returns the task data as a dictionary, or None if the task data is not found.
          
          >>> fs = FileSystem({'taskDir': '~/jsub/'})
          >>> fs.save_task({'id': 1, 'name': 'task1'})
          >>> fs.task_data(1)
          {'id': 1, 'name': 'task1'}
          >>> fs.task_data(2)
          None
          """
          safe_mkdir(os.path.join(self.__jsub_dir, str(task_id), 'taskInfo'))
          task_path = os.path.join(self.__jsub_dir, str(task_id), 'taskInfo', 'repo')
          with open(task_path, 'a+') as f:
              fcntl.flock(f, fcntl.LOCK_EX)
              f.seek(0)
              data_str = f.read()
  
          try:
              return json.loads(data_str)
          except ValueError as e:
              self.__logger.debug(f'JSON decode error on task {task_id}: {e}')
              return None
  
      def __new_task_id(self) -> int:
          task_ids = [int(d) for d in os.listdir(self.__jsub_dir) if os.path.isdir(os.path.join(self.__jsub_dir, d))]
          if not task_ids:
              return 1
          task_ids.sort(key=int, reverse=True)
          return task_ids[0] + 1
  
      def __json_str(self, data: Dict[str, Union[str, int]]) -> str:
          if self.__json_format == 'pretty':
              return json.dumps(data, indent=2)
          return json.dumps(data, separators=(',', ':'))
  
output:     
      def update_task(self, task_id: int, data: Dict[str, Union[str, int]]) -> None:
          """Update task data by the given task ID.
          Overwrites the existing task data with the new data.
          
          >>> fs = FileSystem({'taskDir': '~/jsub/'})
          >>> fs.save_task({'id': 1, 'name': 'task1'})
          >>> fs.update_task(1, {'name': 'updated_task1', 'details': 'new details'})
          >>> fs.find_by_id(1)
          {'id': 1, 'name': 'updated_task1', 'details': 'new details'}
          """
          if 'id' not in data:
              data['id'] = task_id
          safe_mkdir(os.path.join(self.__jsub_dir, str(task_id), 'taskInfo'))
          task_path = os.path.join(self.__jsub_dir, str(task_id), 'taskInfo', 'repo')
  
          data_str = self.__json_str(data)
          with open(task_path, 'w') as f:
              fcntl.flock(f, fcntl.LOCK_EX)
              f.write(data_str)
  